본문 바로가기
Language/파이썬

파이썬 '판다스 데이터 분석' - 결측치 처리 : replace(), dropna(subset= ), fillna(), value_counts().idxmax(), duplicated(), drop_duplicates()

by javapp 자바앱 2021. 7. 17.
728x90

 

데이터프레임에는 원소 데이터 값이 종종 누락되는 경우가 있다.

데이터를 파일로 입력할 때 빠트리거나 파일 형식을 변환하는 과정에서 데이터가 소실되는 것이 주요 원인이다.

일반적으로 유효한 데이터 값이 존재하지 않는 누락 데이터를 NaN( Not a Number ) 으로 표시한다.

 

titanic.csv
0.06MB

'타이타닉 데이터셋을 사용

import seaborn as sns

df= sns.load_dataset('titanic')

 

결측된 데이터 확인

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 15 columns):
 #   Column       Non-Null Count  Dtype   
---  ------       --------------  -----   
 0   survived     891 non-null    int64   
 1   pclass       891 non-null    int64   
 2   sex          891 non-null    object  
 3   age          714 non-null    float64 
 4   sibsp        891 non-null    int64   
 5   parch        891 non-null    int64   
 6   fare         891 non-null    float64 
 7   embarked     889 non-null    object  
 8   class        891 non-null    category
 9   who          891 non-null    object  
 10  adult_male   891 non-null    bool    
 11  deck         203 non-null    category
 12  embark_town  889 non-null    object  
 13  alive        891 non-null    object  
 14  alone        891 non-null    bool    
dtypes: bool(2), category(2), float64(2), int64(4), object(5)
memory usage: 80.7+ KB

 

완전한 데이터는 891 이고
age, deck, embarked, embark_town 에 결측치가 있다.

 

.value_counts(dropna = Falase) 메소드를 이용하여 'deck' 열의 결측치 수를 파악

df['deck'].value_counts(dropna = False) # nan 값을 드랍하지 않는다.
<결과>
NaN    688
C       59
B       47
D       33
E       32
A       15
F       13
G        4
Name: deck, dtype: int64

 

.value_counts(normalize=True) 값의 비중을 구한다.

df['deck'].value_counts(normalize=True) # ascending , sort ..
<결과>
C    0.290640
B    0.231527
D    0.162562
E    0.157635
A    0.073892
F    0.064039
G    0.019704
Name: deck, dtype: float64

 

가장 큰 값을 갖는 값

.value_counts().idxmax()

df['deck'].value_counts().idxmax()

'C'

 

df['deck'].value_counts().idxmin()

'G'

 

누락된 데이터 확인
df.isnull().sum(axis=0)

df.isnull().sum(axis=0)
<결과>
survived         0
pclass           0
sex              0
age            177
sibsp            0
parch            0
fare             0
embarked         2
class            0
who              0
adult_male       0
deck           688
embark_town      2
alive            0
alone            0
dtype: int64

 


 

'deck' 열 결측치 데이터 처리

누락 데이터 제거

.dropna

df.dropna(subset=['deck'])
<class 'pandas.core.frame.DataFrame'>
Int64Index: 203 entries, 1 to 889
Data columns (total 15 columns):
 #   Column       Non-Null Count  Dtype   
---  ------       --------------  -----   
 0   survived     203 non-null    int64   
 1   pclass       203 non-null    int64   
 2   sex          203 non-null    object  
 3   age          184 non-null    float64 
 4   sibsp        203 non-null    int64   
 5   parch        203 non-null    int64   
 6   fare         203 non-null    float64 
 7   embarked     201 non-null    object  
 8   class        203 non-null    category
 9   who          203 non-null    object  
 10  adult_male   203 non-null    bool    
 11  deck         203 non-null    category
 12  embark_town  201 non-null    object  
 13  alive        203 non-null    object  
 14  alone        203 non-null    bool    
dtypes: bool(2), category(2), float64(2), int64(4), object(5)
memory usage: 20.3+ KB

'deck 열에 결측치 행이 제거가 되었다.

 

다중 컬럼 대상 지정 가능

df.dropna(subset=['embarked','embark_town'])
<class 'pandas.core.frame.DataFrame'>
Int64Index: 889 entries, 0 to 890
Data columns (total 15 columns):
 #   Column       Non-Null Count  Dtype   
---  ------       --------------  -----   
 0   survived     889 non-null    int64   
 1   pclass       889 non-null    int64   
 2   sex          889 non-null    object  
 3   age          712 non-null    float64 
 4   sibsp        889 non-null    int64   
 5   parch        889 non-null    int64   
 6   fare         889 non-null    float64 
 7   embarked     889 non-null    object  
 8   class        889 non-null    category
 9   who          889 non-null    object  
 10  adult_male   889 non-null    bool    
 11  deck         201 non-null    category
 12  embark_town  889 non-null    object  
 13  alive        889 non-null    object  
 14  alone        889 non-null    bool    
dtypes: bool(2), category(2), float64(2), int64(4), object(5)
memory usage: 87.3+ KB

 

.dropna(thresh=n, axis=1)

df.dropna(thresh=500, axis=1) # deck 속성의 시리즈가 drop 되었다.
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 14 columns):
 #   Column       Non-Null Count  Dtype   
---  ------       --------------  -----   
 0   survived     891 non-null    int64   
 1   pclass       891 non-null    int64   
 2   sex          891 non-null    object  
 3   age          714 non-null    float64 
 4   sibsp        891 non-null    int64   
 5   parch        891 non-null    int64   
 6   fare         891 non-null    float64 
 7   embarked     889 non-null    object  
 8   class        891 non-null    category
 9   who          891 non-null    object  
 10  adult_male   891 non-null    bool    
 11  embark_town  889 non-null    object  
 12  alive        891 non-null    object  
 13  alone        891 non-null    bool    
dtypes: bool(2), category(1), float64(2), int64(4), object(5)
memory usage: 79.4+ KB

n (500) 개 이상 결측된 데이터가 있는 열을 제거

 

 

결측된 데이터 채우기

 

누락 데이터 평균값으로 대체하기

mean_age = df['age'].mean()
mean_age
<결과>
29.69911764705882

 

df2 = df[df['age'].isnull()]
print(len(df2))
df2.head()
<결과>
177개의 NaN 값 확인

177
	survived pclass	sex	age	sibsp	parch	fare embarked  class	who	adult_male deck	embark_town	alive	alone
5	0	3	male	NaN	0	0	8.4583	Q	Third	man	True	NaN	Queenstown	no	True
17	1	2	male	NaN	0	0	13.0000	S	Second	man	True	NaN	Southampton	yes	True
19	1	3	female	NaN	0	0	7.2250	C	Third	woman	False	NaN	Cherbourg	yes	True

 

 

누락 데이터를 바꿔서 대체할 값으로는 데이터의 분포와 특성을 잘 나타낼 수 있는 평균값, 최빈값 등을 활용한다.

.fillna(v,inplace=True)

원본 객체 변경하려면 inplace=True 옵션 추가

df['age'].fillna(mean_age,inplace=True)
df2 = df[df['age'].isnull()]
print(len(df2))
df2
<결과>
0
survived	pclass	sex	age	sibsp	parch	fare	embarked	class	who	adult_male	deck	embark_town	alive	alone

결측치가 없는 것을 확인

 

df['age'].isnull()
0      False
1      False
2      False
3      False
4      False
       ...  
886    False
887    False
888    False
889    False
890    False
Name: age, Length: 891, dtype: bool

 

누락된 값을 최빈값으로 치환하기

df3 = df[df['embark_town'].isnull()]
print(df3.index)
df3
<결과>
Int64Index([61, 829], dtype='int64')
	survived pclass	sex	age	sibsp	parch	fare	embarked  class	who	adult_male deck embark_town alive alone
61	1	1	female	38.0	0	0	80.0	NaN	First	woman	False	B	NaN	yes	True
829	1	1	female	62.0	0	0	80.0	NaN	First	woman	False	B	NaN	yes	True

 

최빈값 찾기

most_freq_town = df['embark_town'].value_counts().idxmax()
most_freq_town

'Southampton'

 

최빈값 채워넣기

df['embark_town'].fillna(most_freq_town).iloc[825:830]
<결과>
825     Queenstown
826    Southampton
827      Cherbourg
828     Queenstown
829    Southampton
Name: embark_town, dtype: object

829 행에 값이 잘 들어간 것을 볼 수 있다.

 

1행 이전 값으로 채워넣기

method='ffill'

df['embark_town'].fillna(method='ffill').iloc[825:830]
<결과>
825     Queenstown
826    Southampton
827      Cherbourg
828     Queenstown
829     Queenstown
Name: embark_town, dtype: object

 

누락 데이터가 NaN으로 표시되지 않은 경우
'?' 이거나 '-' 등으로 되어 있을때 np.nan 을 사용하여 변경하는 것이 좋다.

df_.replace('-', np.nan, inplace=True)

 

 

중복값 확인

df.duplicated()
0      False
1      False
2      False
3      False
4      False
       ...  
886     True
887    False
888    False
889    False
890    False
Length: 891, dtype: bool

886행에 중복값이 있는 것을 확인

 

.drop_duplicates()

중복값 제거

df2 = df.drop_duplicates()
df2.duplicated()
<결과>
0      False
1      False
2      False
3      False
4      False
       ...  
885    False
887    False
888    False
889    False
890    False
Length: 784, dtype: bool

886행이 없어진 것을 확인

 

 

댓글