1. matplotlib의 hist함수
먼저 matplotlib의 hist함수이다.
구간을 설정할 수 있기 때문에 대상열의 고유값의 종류가 많거나 연속형 타입일 경우 자주 사용한다.
① Age(나이)와 Survived의 관계
첫번째로 profiling할 특성은 Age(나이)이다.
import matplotlib.pyplot as plt
%matplotlib inline
plt.hist(train.loc[train['Survived']==0, 'Age'].dropna(), # train set에서 생존=0인 행에서 'Age'열값만 가져온 데이터 프레임, 결측치있는 행은 제거,
bins=30, alpha=0.5, label='0') # 히스토그램 설정(bin=구간의 개수, alpha=투명도, label=범례에 표시될 라벨)
plt.hist(train.loc[train['Survived']==1, 'Age'].dropna(), # train set에서 행을 추출, [생존=0, 나이]인 행, 결측치있는 행은 제거,
bins=30, alpha=0.5, label='1')
plt.xlabel('Age')
plt.ylabel('count')
plt.legend(title='Survived')
- matplotlib.pyplot을 plt라는 이름으로 import한다. (%matplotlib inline는 그래프를 출력창에서 확인하기 적어야한다.)
- plt.hist()함수
여기서 사용한 파라미터는 4가지이다.
첫번째 파라미터 : train.loc[train['Survived']==0, 'Age'].dropna()
=> 'Survived'의 값이 0인 레코드들에서 'Age'열 값만 가져온다. 만약 결측값이 있다면 해당 레코드는 제거
(* 기본 지식) 데이터프레임.loc[조건, 대상 열이름] "loc : location" -> 조건에 해당하는 레코드들의 대상 열 값들만 뽑아서 새로운 데이터프레임으로 반환
데이터프레임.iloc[행 인덱스, 대상 열이름] "iloc: index location" -> 행 인덱스에 해당하는 레코드들의 대상 열값들만 뽑아서 새로운 데이터프레임으로 반환
dropna() -> 결측치있는 레코드 제거 |
두번째 파라미터 : bins = 30
bins는 구간의 개수를 의미한다.
세번째 파라미터 : alpha = 0.5
alpha는 투명도를 의미한다. (0.5이므로 막대그래프가 반투명하다는 것)
네번째 파라미터 : label = '0'
label은 범례에 표시될 라벨을 의미한다. (그래프 위에 값 종류 표시)
- plt.xlabel : x 축 이름
- plt.ylabel : y축 이름
- plt.legend(title='Survived') : 범례 이름
결과값 :
우선 0이 사망, 1이 생존이다.
우선 값의 전체적인 분포는 0일때나, 1일때나 비슷한 점을 볼 수 있다. 10대 후반~30대 중반이 주 고객이었던 것으로 보인다.
하지만 이는 그저 고객들의 나이 분포일 뿐 Survived와의 관계가 아니다.
기본 전제를 깔아보자.
"사망자의 경향과 생존자의 경향이 다를수록 좋다."
이제 0(생존)일때의 경향과 1(사망)일때의 경향을 비교해보자.
전체적인 증감은 비슷해 보인다.
하지만 0(생존)의 경우 20에서 30으로 넘어갈때 계속 증가하지만
1(사망)에서는 20에서 30으로 넘어갈때 오히려 감소한다.
이제 버릴지 살릴지 판단해야한다.
위에서 찾은 차이점이 도움이 될까? 아니면 없애는게 나을까?
차이점이 별로 크지 않으니 버려야할까?
대답은 일단 살려두자이다.
차이점이 크지 않더라도 다른 특성과의 시너지를 보일 수 있다.
예를 들어 성별이 남성이고 해당 나이대일 경우 거의 100% 사망했을 수도 있다. (구명보트에서의 양보라던지의 이유로...)
상관계수로만 단순히 판단할 수 없는 이유 중 하나이기도 하다.
상관계수를 확인해보자.
train['Age'].corr(train['Survived'])
결과값을 보면 0.08이다. -1~1사이의 값 중 0.1도 안되는 값이라니 이것만 보면 버리는게 무조건 맞다.
하지만 시각화해서 확인했을 때는?
전체적인 경향에서의 변별력은 떨어지지만, 20~30대에서의 차이가 있으므로 아직 버리기는 이르다고 판단했다.
②Fare(운임비용)와 Survived의 관계
두번째로 profiling할 특성은 Fare(운임비용)이다.
코드는 위와 거의 동일하다.
plt.hist(train.loc[train['Survived']==0, 'Fare'].dropna(),
range=(0,250),bins=50, alpha=0.5, label='0')
plt.hist(train.loc[train['Survived']==1, 'Fare'].dropna(),
range=(0,250),bins=50, alpha=0.5, label='1')
plt.xlabel('Fare')
plt.ylabel('Survived')
plt.legend(title='Survived')
plt.xlim(-5, 250)
(*기본지식) - range=(0,250) : hist함수의 파라미터 중 하나로 히스토그램을 그릴 범위를 정한다. => Fare의 값이 0~250까지만 막대로 표현된다.
- plt.xlim(-5, 250) : 그래프의 x축 상한 => 그래프에 Fare값이 -5일때부터 250일때까지만 표시된다. |
결과값:
우선 전체적인 경향으로는 0~50 사이에 거의 모든 티켓요금이 몰려있다.
아마 좋은 객실보다는 평범한 객실이 많았기 때문이었을거로 예상된다.
내가 생각하기에는 Fare는 살릴지 말지 애매한 특성이다.
운임비용이 10 정도일 때 생존자 수와 사망자 수가 매우 많이 차이나긴하지만
생존자 수, 사망자 수 모두 10근방에서 가장 많다는 "경향"은 비슷하다.
이러면
<"Fare가 10정도일 때 생존자와 사망자 수의 차이가 크다."는 현상은 생존 여부를 예측하는데에 중요하지 않다.>
라는 가설을 세울 수 있다.
이제 이 가설을 입증해보자.
"경향은 비슷한데 인원수의 차이가 크다."의 원인을 찾으면 된다.
print("사망자 수:",len(train.loc[train['Survived']==0]))
print("생존자 수:",len(train.loc[train['Survived']==1]))
사망자, 생존자 수를 각각 확인했을 때 사망자가 생존자보다 많다.
즉 절대적인 사망자 수가 많아서 Fare가 10 근방일 때 생존, 사망자 인원의 차이가 커보이는 것이지,
생존 여부를 예측할 때의 실질적인 변별력은 없을 가능성이 높다는 것이다.
따라서 Fare는 그다지 매력적인 특성은 아닌 것으로 보인다.
(하지만 책에서는 포함시켜서 진행했으므로 일단 보류한다.)
(아마 절대적인 인원수 차이가 있다고 해도 저만큼의 차이는 유의미하다고 본것 같다.)
이번 포스트는 matplotlib를 활용한 시각화였다.
중점은?
- 데이터를 보고 어떤 현상을 발견해내는지
- 해당 현상을 통해 어떤 가설을 세울 수 있는지
- 해당 가설의 근거는 무엇인지
- 최종 판단
+ 상관계수만으로 판단할때의 취약점
다음 포스트에서는 seaborn을 활용한 시각화를 알아보자!