[9] 누락된 데이터 다루기 (파이썬 데이터분석, 머신러닝)

2021. 2. 5. 13:55머신러닝 교과서 with 파이썬, 사이킷런, 텐서플로

728x90
반응형

누락된 데이터 다루기

- 누락된 데이터는 크게 두 가지 방식으로 다룰 수 있다.

 

1. 누락된 데이터가 있는 표본(Row, Sample)이나 열(Column, feature)을 삭제한다.

2. 보간기법을 사용해 누락된 데이터를 예측한다.

- 평균, 중간값, 빈도수, 상수 등을 사용한다.

 

 

코드를 활용해 한번 확인해보자.

 

0. 누락된 데이터가 포함된 데이터 프레임 생성

필요한 라이브러리 불러오기

import pandas as pd # 데이터프레임 만들 때 사용
import numpy as np # 벡터연산을 위해 사용 
from sklearn.impute import SimpleImputer # 보간기법에 사용
from io import StringIO # 데이터프레임 만들 때 활용

누락된 데이터가 포함된 데이터프레임 만들기

... """A,B,C,D
... 1.0,2.0,3.0,4.0
... 5.0,6.0,,8.0
... 10.0,11.0,12.0"""
df = pd.read_csv(StringIO(csv_data))
df

데이터프레임은 values를 사용해 넘파이 어레이 형태로 변환할 수 있다.

# We always get Numpy array from Pandas Dataframe
df.values

열별로 누락된 데이터 확인하기

df.isnull().sum()

C열과 D열에 누락된 데이터가 하나씩 있는 것을 확인할 수 있다.

 

[1] 표본이나 열 삭제하기

# Delete Samples
df.dropna(axis = 0)

# Delete Columns
df.dropna(axis = 1)

axis에 0의 값을 주면 레코드를 기준으로 삭제하고 axis에 1의 값을 주면 열을 기준으로 삭제한다.

이는 데이터프레임을 사용하는 여러 함수에서도 필요한 지식이므로 기억해두는 것이 좋다.

 

# Parameters of 'dropna' method.
## When there are NaN values in all column, delete samples.
df.dropna(how='all')

dropna함수는 how = 'all'는 하나의 샘플에 모든 값이 누락됐을 경우 삭제하는 파라미터이다.

모든 정보가 없는 샘플은 필요가 없으므로 삭제하는 것이 좋다.

 

## When numbers of values is less than certain standard point, delete samples.
df.dropna(thresh=4)

thresh는 삭제하는 기준을 정해주는 파라미터이다.

위의 식에서는 4의 값을 주었으므로 4개 미만의 값을 가지고 있는 샘플의 경우 삭제하라는 의미이다. 

## When there are NaN values in certain columns, delete samples.
df.dropna(subset = ['C'])

subset은 특정 열에 누락된 값이 존재할 경우 그 샘플을 삭제하라고 하는 파라미터이다.

 

[2] 보간기법을 사용해 누락된 데이터 예측하기

- 다양한 방법으로 보간기법을 사용할 수 있지만 사이킷런에서는 보간기법을 간단하게 사용할 수 있도록 라이브러리를 별도로 제공해준다.

 

평균

# We have to input data as numpy array, not pandas dataframe
## mean by columns
imr = SimpleImputer(missing_values = np.nan, strategy = 'mean')
imr = imr.fit(df.values)
imputed_data = imr.transform(df.values)
imputed_data

사이킷런의 주요 특징 중 하나는 추정기 API를 사용한다는 것이다. 이 추정기의 주요 메소드는 fit과 transform이다. fit을 사용하면 모델을 학습시키고 transform을 사용해 학습한 파라미터로 데이터를 변환하는 것이다.

주의할 점은 변환하려는 데이터 배열은 모델 학습에 사용한 데이터의 특성 개수와 같아야한다는 점이다. 보간기법에서만 사용되는 것이 아니라 사이킷런 모델을 사용할 때도 사용되기에 추정기에 대해 어느정도 이해는 하고 있어야한다. 

* 추가로 fit_transform을 통해 한번에 사용도 가능하다.

 

 

missing_values와 어떤 보간기법을 사용할 것인지에 대해 입력하면 자동으로 열을 기준으로 누락된 데이터를 추가해준다. 

 

중간값

## median by columns
imr = SimpleImputer(missing_values = np.nan, strategy = 'median')
imr = imr.fit(df.values)
imputed_data = imr.transform(df.values)
imputed_data

빈도수

## most frequent by columns
### It is imputated by first value in such columns when number of frequency of values is same.
imr = SimpleImputer(missing_values = np.nan, strategy = 'most_frequent')
imr = imr.fit(df.values)
imputed_data = imr.transform(df.values)
imputed_data

* 빈도수가 동일할 경우 먼저나오는 값을 기준으로 대체된다.

 

사이킷런 추정기를 사용하지 않더라도 다음과 같은 방법을 사용하면 누락된 데이터를 대체할 수 있다.

# It can be worked by this way
## mean by columns
imputed_data = df.copy()
imputed_data['C'] = df['C'].fillna(df['C'].mean())
imputed_data['D'] = df['D'].fillna(df['D'].mean())
imputed_data

해당 경우에는 데이터프레임의 형태가 그대로 남는다.

* 참고로 나는 이 방법을 사용한다.

 

행을 기준으로 값을 입력하고싶다면 다소 복잡한 방법을 사용해야한다.

빈도수

# If you want to imputate by samples, you can do like this
from sklearn.preprocessing import FunctionTransformer
ftr_imr = FunctionTransformer(lambda x: imr.fit_transform(x.T).T, validate = False)
imputed_data = ftr_imr.fit_transform(df.values)
imputed_data

T는 벡터연산에서의 Transpose로 차원의 형태를 바꾸는 건데, 쉽게말해 행과 열의 위치를 바꿔주는 것이다. 

다소 복잡해보이는 방식이므로 굳이 다음과같은 방식으로 할 필요가 있나 싶기는 하다. 그래서 나는 아래의 방법을 사용한다.

# You can also handle NaN data by samples like this
imputed_data = df.copy()
imputed_data.iloc[1] = imputed_data.iloc[1].fillna(imputed_data.iloc[1].mean())
imputed_data.iloc[2] = imputed_data.iloc[2].fillna(imputed_data.iloc[2].mean())
imputed_data

 

iloc는 데이터프레임의 행을 기준으로 값을 찾아주는 메소드이다. 

예시에선 데이터의 개수가 매우 적으므로 직접 입력을 해주었지만 만약 데이터가 많아질 경우엔 for문을 사용하거나 apply를 사용해서 누락된 데이터를 다루면 된다.

 

참고로 데이터가 무수히 많아질 경우엔 for문도 매우 오래걸리므로 apply(lambda x:x.fillna(x.mean()))를 사용한다면 금방 해결할 수 있다.

728x90
반응형