[Python.TitanicOverview] 데이터 전처리 2 - 결측치 처리
2021. 2. 26. 05:00ㆍPython과 머신러닝/최종 실습 (Titanic Dataset)
1. 결측치 처리 예제
In [1]:import pandas as pd import numpy as np
In [2]:#https://chrisalbon.com/python/data_wrangling/pandas_missing_data/
raw_data = {'first_name': ['Jason', np.nan, 'Tina', 'Jake', 'Amy'],
'last_name': ['Miller', np.nan, 'Ali', 'Milner', 'Cooze'],
'age': [42, np.nan, 36, 24, 73],
'sex': ['m', np.nan, 'f', 'm', 'f'],
'preTestScore': [4, np.nan, np.nan, 2, 3],
'postTestScore': [25, np.nan, np.nan, 62, 70]}
df = pd.DataFrame(raw_data, columns = ['first_name', 'last_name', 'age', 'sex', 'preTestScore', 'postTestScore'])
df
Out[2]:
- 이 데이터는 chrisalbon.com에서 가져온 예제이다.
- Out[2]에 나온 것과 같은 데이터가 있다고 보자. 이 중 결측치가 많은데, 결측치 확인부터 코드로 하는 것이 가장 좋다. (매번 수많은 데이터를 직접 확인하기란 불가능하다)
2. 결측치의 비율(%) 확인하기
In [3]:df.isnull().sum() / len(df)*100
Out[3]:first_name 20.0
last_name 20.0
age 20.0
sex 20.0
preTestScore 40.0
postTestScore 40.0
dtype: float64
- In[3]은 각 column/series별로 결측치가 존재하는 비율을 보기 위한 코드이다.
- 이 한 줄의 코드로 어떤 X변수가 결측치가 많은지 한 번에 확인할 수 있고, 그에 따라 처리를 할 수 있을 것이다.
3. 결측치 처리방법 1 : X 변수 중 하나라도 결측치가 있다면 row 제거
In [4]:df.dropna()
Out[4]:
4. 결측치 처리방법 2 : X 변수가 전부 결측치일 경우에 row 제거
In [5]:df.dropna(how='all')
Out[5]:
- how='all' : 모든 X변수가 NaN일 때만 row를 drop 한다
5. 결측치 처리방법 3 : X 변수가 전부 결측치일 경우에 column 제거
In [6]:df.dropna(axis=1, how='all')
Out[6]:
- axis=1 : Column에 아무런 valid data가 없을 경우 (전부 NaN일 경우) Column을 제거한다.
6. 결측치 처리방법 4 : n개 미만의 X변수가 valid 하면 drop
In [7]:df.dropna(thresh=1)
Out[7]:
- dropna(thresh=1)
- 각 row별로 thresh 개수 이상의 valid data가 있을 경우에는 두고,
- thresh 개수 미만의 valid data가 있을 경우에는 drop 한다.
7. 결측치 처리방법 5 : 데이터 채우기 (평균값으로 결측치 대체)
In [8]:cleaned_df = df.dropna(axis=1, how='all')
cleaned_df = df.dropna(axis=0, how='all')
cleaned_df
In [9]:fillna_df = cleaned_df.copy()
fillna_df['preTestScore']=cleaned_df['preTestScore'].fillna(cleaned_df['preTestScore'].mean())
fillna_df
Out[9]:
- In[9]은 cleaned_df의 preTestScore의 결측치를 평균으로 대체하였고, 대체된 값을 fillna_df로 옮겼다
- Out[9]에서 보다시피 Tina Ali의 PreTestScore가 NaN에서 3.0으로 변경된 것을 확인할 수 있다.
- 결측치가 많지 않은 경우에는 이와 같이 평균값으로 결측치를 대체하는 것도 좋은 방법이다.
8. 결측치 처리방법 6 : 데이터 채우기 (그룹별 평균값으로 결측치 대체하기)
In [10]:cleaned_df.groupby('sex')['postTestScore'].mean()
Out[10]:sex
f 70.0
m 43.5
Name: postTestScore, dtype: float64
In [11]:fillna_df['postTestScore'] = cleaned_df['postTestScore'].fillna(cleaned_df.groupby('sex')['postTestScore'].transform('mean'))
fillna_df
Out[11]:
- 결측치를 전체 평균으로 넣는 것이 잘못된 방식일 수도 있다.
- 이럴 때에는 최대한 세분화된 분류에 따라서 분류별 평균을 적용하는 것이 좋다.
- groupby 하여 그룹별 평균을 계산하고, 그룹별 평균으로 fillna를 하는 것이 한 단계 더 발전한 방법일 것이다.
9. Titanic 예제에서 결측치 채우기
In [11]:pd.options.display.float_format = '{:.2f}'.format
In [12]:df.isnull().sum() / len(df)*100
Out[12]:PassengerId 0.00
Pclass 0.00
Name 0.00
Sex 0.00
Age 20.09
SibSp 0.00
Parch 0.00
Ticket 0.00
Fare 0.08
Cabin 77.46
Embarked 0.15
dtype: float64
In [13]:df[df['Age'].notnull()].groupby(['Sex'])['Age'].mean()
Out[13]:Sex
female 28.69
male 30.59
Name: Age, dtype: float64
In [14]:df[df['Age'].notnull()].groupby(['Pclass'])['Age'].mean()
Out[14]:Pclass
1 39.16
2 29.51
3 24.82
Name: Age, dtype: float64
In [15]:df['Age'].fillna(df.groupby('Pclass')['Age'].transform('mean'), inplace=True)
In [16]:df.isnull().sum() / len(df)*100
Out[16]:PassengerId 0.00
Pclass 0.00
Name 0.00
Sex 0.00
Age 0.00
SibSp 0.00
Parch 0.00
Ticket 0.00
Fare 0.08
Cabin 77.46
Embarked 0.15
dtype: float64
- In[12] : Titanic에서도 동일하게 결측치의 비율을 보면, Age의 결측치부터 처리가 필요해 보인다.
- In[13] : Age의 평균을 Sex별로 보니 남녀 간의 차이가 크지 않다.
- In[14] : Age의 평균을 Pclass별로 보니 차이가 더 명확하여, Pclass별 평균을 데이터에 적용하는 것이 더 유의미하고 판단할 수 있다.
- In[15] : pclass별 평균을 갖고 df['Age']를 채워준다.
반응형
'Python과 머신러닝 > 최종 실습 (Titanic Dataset)' 카테고리의 다른 글
[Python.TitanicOverview] 데이터 입력 및 전처리 (0) | 2021.02.25 |
---|