Python으로 배우는 데이터 전처리 이해(I) - 결측값 처리
결측값(Missing Value) 처리
데이터 정제 (Data Cleaning) 이란 데이터 전처리한 과정으로 결측값, 잡음, 이상값 등 데이터 오류를 일으킬 수 있는 요인을 삭제하고, 불일치를 해결하여 데이터의 신뢰도를 높이는 과정이다.
결측값 처리가 하나의 데이터 정제 과정이다.
이러한 데이터 정제과정을 해주지 않으면 분석 모델의 정확도가 떨어지고 기대하는 예측값을 얻을 수 없다.
데이터 오류의 원인에는 결측값 ,노이즈,이상값,모순,불일치, 중복이 있다.
노이즈는 임의적 요소로서 변수를 본래의 참값에서 벗어나게 하는 오류이고,
이상값은 데이터의 범위에서 많이 벗어난, 요소이다. (잘못 기록한 것이 아님)
결측값(Missing Value) 는 값이 존재하지 않고 비어있는 상태를 말한다.
NaN, Na, Inf, Null 등으로 표현한다.
결측값의 유형에는 완전 무작위 결측, 무작위 결측, 비 무작위 결측이 있다.
1 ) 완전 무작위 결측 : 결측값이 다른 변수들과 아무런 상관이 없는 경우
2) 무작위 결측 : 결측값이 다른 변수와 연관이 있어 발생되었지만 , 그 변수가 자체가 결과에 영향을 미치지 않는 경우
Ex: 여성은 나이를 공개할 가능성이 적다. => 그렇지만 여성과 나이는 관계가 없다.
3) 비 무작위 결측 : 결과에 영향이 있는 변수 때문에 결측값이 발생되는 경우
Ex : 키가 작은 사람은 몸무게를 공개할 가능성이 적다. => 결측값이 있는 경우키가 평균보다 작을 확률 높다.
데이터 결측값의 처리 절차는
결측값 식별 => 결측값 부호화 => 결측값 대체
순으로 수행된다.
■ 결측값의 처리 기법
1) 삭제 (Deleting) : 말 그대로 삭제. 단일값 삭제와 목록 삭제가 있다.
정보 손실이 일어날 수 있으므로 지양한다.
2) 대치 (Imputation) : 특정 대표값으로 혹은 회귀분석, 분류 등 여러 방법을 통해 추정된 값으로 대체한다.
일반적으로 삭제보다 대치를 많이 사용한다.
단순 대치법과 다중 대치법이 있다.
단순 대치법은 특정 값을 결측값으로 대치한다. 이 때 대치값은 평균값 ,최빈값 ,중앙값 등이 있다.
단순 대치법에는 또다시 완전 분석법, 단순 확률 대치법 (핫덱 대치, 콜드덱 대치, 근접 이웃 대치) 가 있다.
평균대치법 (비조건부 평균 대치, 조건부 평균대치) 도 있다.
다중 대치법은 결측값 추정을 여러 번 반복하여 대치된 데이터셋을 생성 후 결측값을 대치하는 방법이다.
다중 대치법을 사용할 시엔 과소추정 문제를 낮출 수 있다.
결측값 처리 실습
1. 결측값을 확인한다.
# 필요 라이브러리를 import 해준다.
import pandas as pd # pandas package
import numpy as np # numpy package : np.nan 이용 결측값 생성
import matplotlib.pyplot as plt # matplotlib 시각화 패키지
import seaborn as sns # seaborn 시각화 패키지
필요한 라이브러리를 import 해주었다.
np 는 np.nan 을 이용해서 결측값을 생성해주기 위해서 불러왔다.
matplotlib 는 데이터를 시각화 해줄 수 있는 라이브러리이다.
matplotlib.pyplot 을 사용할 것이다,
seaborn 도 데이터 시각화 패키지이다. matplotlib 패키지에 기본적으로 의존한다.
import os
if os.name == 'nt' :
font_family = "Malgun Gothic"
else :
font_family = "AplleGothic"
시각화 할 때 (?) os 에 따른 폰트 깨짐 제거를 위해서 Font 를 지정해주었다.
sns.set(font=font_family, rc = {"axes.unicode_minus" : False})
from sklearn.impute import SimpleImputer
from sklearn import linear_model
값이 깨지는 문제 해결을 위해서 seaborn 에서 파라미터 값을 설정해주었다. (이거 뭔 말인지 모르겠다)
sklearn 은 scikit-learn 인데 , Python 을 대표하는 머신러닝 라이브러리이다.
내가 머신러닝을 한거라고 ?
2. 결측값 데이터 생성
결측값 데이터를 생성해준다.
temp_dict = {'A열' : [np.nan, 4, 6, 5, 5, np.nan],
'B열' : ['a', 'a', np.nan, 'b', 'b','b'],
'C열' : [np.nan, 3.5, -1.5, np.nan, 5.5, np.nan],
'D열' : [1, 0, 1, 0, 1, 1]
}
missing_data = pd.DataFrame(temp_dict)
missing_data
temp_dict 라는 결측값 데이터를 만들고 , 이걸 데이터 프레임으로 만들어주었다.
3. 결측값 데이터 확인
info() 를 사용해서 데이터에 대한 전반적인 정보를 확인할 수 있다.
행과 열의 크기, 컬럼명, 컬럼을 구성하는 데이터 유형, 결측값 등을 알 수 있다.
데이터프레임 전체의 결측값을 확인하려면
df.isnull(), isnull(df), df.notnull(), notnull(df) 등을 써도 좋다.
index 는 인덱스 범위이다. count 값으로 결측값 유무를 확인한다.
총 6개인데.. A열은 2개, B열은 1개, C열은 3개의 null 값이 있는 것을 확인할 수 있다.
6개에서 비는 값을 확인한 것이다.
위에서 말한 isnull() 을 사용해서 결측값을 확인했다.
True 라면 결측값, False 라면 결측값이 아니다.
sum() 을 이용해서 결측값의 갯수도 확인했다.
위에서 확인했는데 솔직히 왜 다시 print를 써서 확인하는 지는 모르곘으나
아무튼 간에 결측값 갯수를 다시 확인했다.
결측값을 시각화하자.
- matplotlib : 파이썬에서 데이터를 차트나 plot 으로 그려주는 시각화 패키지
- seaborn : matplotlib 를 기반으로 해서 색상 테마와 통계용 차트 등의 기능을 추가한 시각화 패키지
C열의 결측치가 가장 많은 것이 시각화한 그래프로 확인되었다.
결측값 처리 - 삭제법
삭제법은 앞에서 말했듯이 , 결측값이 있는 행과 열 자체를 그냥 지워버리는 방법이다.
결측값이 80% 에 가까운 경우, 그 변수 자체를 제거하는 방식이다.
결측값을 지우면서 데이터 자체의 편향이 생길 수 있다.
dropna() 를 사용해보자.
axis = 0 이면 행을 말하는 것이다.
결측값이 들어있는 행이 완전히 사라진 것을 볼 수 있다.
결측값이 하나만 있어도 그냥 냅다 drop 해버렸다.
axis =1 이면 열을 말하는 것이다.
결측값이 하나라도 들어있는 열은 다 날려버렸다.
위에서 확인했을 때, 결측값이 없는 열은 D열 뿐이었으니 결과가 D열만 덩그러니 남으면
맞게 나온 것이다.
thresh 파라미터를 이용해서 결측값이 있는 열을 날려보자.
결측값 제외 후 행이 5개 미만인 열은 A,C열 이므로 날아갔다.
thresh = 5 이므로 결측값을 날렸을 때 행이 5개 미만인 열들은 다 날아갔다.
B는 결측값을 날려도 5개의 데이터가 남아있어서 날아가지 않았다.
B열에 null값이 존재하는 raw 를 날렸다.
B열에는 2 행에 (세번째 열) 결측값이 있었기 때문에 날아갔다.
결측값 처리 - 대치법(Imputation)
- fillna() : DataFrame 에서 결측값을 원하는 값으로 변경하는 함수
- SimpleImputer () : sklearn 의 열의 평균이나 중앙값, 최빈으로 대체하게 해 주는 클래스
- linear_model() : sklearn 선형 회귀법을 이용하여 값을 대체 (조건부 평균 대치법)
결측값을 다시 확인한다.
1 ) fillna()
DataFrame 에서 결측값을 원하는 값으로 변경하는 함수
특정값으로 채울 수 있다. 특정값, 평균 : mean , 최소값 : min 등
method : ffill(이전 값으로 채우기), bfill(이후 값으로 채우기)
0으로 채워보자.
1열에 있던 결측값이 0.0 으로 바뀌었다.
missing_data["A열"] = missing_data["A열"].fillna(0)
이 명령어를 치면 값이 업데이트 된다.
이전값으로 대치해주는 ffill 을 사용해보자.
a로 대치되었다. 이전 값이 a였기 때문이다.
이후값으로 대치해주는 bfill 을 사용해보자.
method = 'bfill'
이전에는 a 였던 값이 b가 된 것을 확인할 수 있다.
평균으로
연속형 데이터들만 해당된다.
숫자형 데이터였던 열들은 다 평균으로 대치되었다.
B열은 숫자형이 아니라 문자형이기 때문에 평균계산이 되지 않아 아직도 Null값이다.
2 ) Simplemputer()
sklearn 의 열 평균이나 중앙값, 최빈으로 대체하게 해주는 클래스이다.
strategy (most_frequent : 최빈값 , mean : 평균값, median : 중앙값)
A열의 최빈값을 결측값에 대체한다.
나머지 열의 결측값을 모두 최빈값으로 대체한다.
3) linear_model()
sklearn 의 선형 회귀법을 이용해서 값을 대체한다.
sklearn 에 대해서는 ...나중에 따로 또 알아보자 ..
실습 데이터를 불러왔다.
data = pd.read_csv("http://archive.ics.uci.edu/ml/machine-learning-databases/abalone/abalone.data",
header = None,
names = ['sex', 'length', 'diameter', 'height',
'whole_weight', 'shucked_weight',
'viscera_weight', 'shell_weight', 'rings']
)
20개의 테스트 데이터만 저장하고,
결측값 데이터를 생성했다.
학습 데이터를 생성한다. X,Y 에 결측값을 삭제한다.
X로 y 를 결정하는 회귀..
선형회귀 모형을 만들었다. (lin_reg)
모델에 X 와 y를 피팅하여 선형회귀 모델을 구성했다 . (lin_reg_model)
선형회귀 모델로 whole_weight 추정값을 계산했다.
diameter ,height, shell_weight 를 사용했다.
이렇게 예측해온 whole_weight 예측값을 결측값에 대체한다.
아까 배운 fillna() 를 이용할 것이다.
whole_weight 열을 보면 위에서 나온 예측값들이 잘 반영된 것을 알 수 있다.
※ 저의 모든 데이터 분석 자료는 모두 공공 빅데이터 청년 인턴 교재들을 참고합니다.