[ 변수 처리] 결측치 대체 알고리즘 MissForest Imputation 연습
2019. 12. 11. 22:59ㆍ분석 Python/Data Preprocessing
MissForest로 결측치 대체를 하려고하는 것이 목적이다.
그래서 일단 임의의 데이터를 만들고 진행한다.
from missingpy import MissForest
import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
tr1 = list("ABCD")
tr2 = ['pooh', 'rabbit', 'piglet', 'Christopher']
va1 = list("ABCDE")
va2 = ['pooh', 'rabbit', 'piglet', 'Christopher', "bird", "coco"]
tr1_ = np.random.choice(tr1, 1000 , p=[0.5, 0.1, 0.1, 0.3])
va1_ = np.random.choice(va1, 500 , p=[0.4, 0.1, 0.1, 0.3,0.1])
tr2_ = np.random.choice(tr2, 1000 , p=[0.5, 0.1, 0.1, 0.3])
va2_ = np.random.choice(va2, 500 , p=[0.5, 0.1, 0.09, 0.25,0.05,0.01])
tr_n = np.random.normal(size = (1000 , 10))
va_n = np.random.normal(size = (500 , 10))
col = [ "Cols{}".format(i) for i in np.arange(10)]
Tr = pd.DataFrame(tr_n, columns= col)
Va = pd.DataFrame(va_n , columns= col)
Tr["Col_Fac1"] = tr1_
Tr["Col_Fac2"] = tr2_
Va["Col_Fac1"] = va1_
Va["Col_Fac2"] = va2_
Tr.head()
이제 이러한 데이터에서 결측을 만들어보자.
가정은 MCAR로 임의로 만들었다. 위에서 만들수도 있지만, 그냥 여기서 MaskVector를 만들어서 진행했다.
No , ori = Tr.shape
p_miss = 0.2
p_miss_vec = p_miss * np.ones((No,1))
Missing = np.zeros((No,ori))
ori_Missing = np.zeros((No,ori))
for idx , st in enumerate(np.arange(ori)) :
A = np.random.uniform(0., 1., size = [No,])
A1 = np.expand_dims(A , axis = 1)
B_ = A > p_miss_vec[idx]
ori_Missing[:,idx] = 1.*B_
B = A1 > p_miss_vec
No , ori = Va.shape
p_miss = 0.2
p_miss_vec = p_miss * np.ones((No,1))
Missing = np.zeros((No,ori))
va_Missing = np.zeros((No,ori))
for idx , st in enumerate(np.arange(ori)) :
A = np.random.uniform(0., 1., size = [No,])
A1 = np.expand_dims(A , axis = 1)
B_ = A > p_miss_vec[idx]
va_Missing[:,idx] = 1.*B_
B = A1 > p_miss_vec
MaskVector = 1-ori_Missing
VaMaskVector = 1-va_Missing
Tr[MaskVector == 1 ]= np.nan
Va[VaMaskVector==1] = np.nan
그 다음에 간단한 전처리 진행을 했다.
fac_var = ["Col_Fac1" , "Col_Fac2"]
change_nan = {}
for col in fac_var :
unis = list(set(Va[col].unique()).difference(set(Tr[col].unique())))
temp = {}
for uni in unis :
temp[uni] = np.nan
change_nan[col] = temp
Va2 = Va.replace(change_nan)
그 다음에 label encoder를 적용하기 위해 결측치를 다른 값으로 대체하고 해당 encoder값을 저장했다.
le_info = {}
for col in fac_var :
Tr[col] = Tr[col].fillna("NaN")
Va2[col] = Va2[col].fillna("NaN")
le = LabelEncoder()
x = Tr[col].unique()
le_info[col] = le.fit(x)
le.fit(x)
Tr[col] = le.transform(Tr[col])
Va2[col] = le.transform(Va2[col])
le_info[col].classes_
결측을 NaN으로 만들었기 때문에 다시 MaskVector를 사용해서 결측으로 만들었다. 아니면 해당 encoding 값을 바꾸는 것도 다른 하나의 방법일 것이다.
Tr[MaskVector == 1 ]= np.nan
Va2[VaMaskVector==1] = np.nan
Va2.head()
이제 데이터는 다 구성했으니, MissForest 결측치 대체 알고리즘을 돌려보자!
큰 특징은 cat_var로 범주형 변수의 index 정보를 줘야 한다!
UseCols = Tr.columns.tolist()
cat_var = [idx for idx , col in enumerate(UseCols) if col in fac_var]
MISSForest_algo = MissForest(verbose = 0, n_jobs = -1 , max_depth=5)
MISSForest_algo.fit(X =Tr , cat_vars= cat_var)
Tr_imputed = MISSForest_algo.transform(Tr)
Tr_imputed = pd.DataFrame(Tr_imputed, columns= UseCols
Tr_imputed[fac_var] = Tr_imputed[fac_var].astype(int)
Va_imputed = MISSForest_algo.transform(Va2)
Va_imputed = pd.DataFrame(Va_imputed, columns= UseCols)
Va_imputed[fac_var] = Va_imputed[fac_var].astype(int)
## 다시 변형
for col in fac_var :
Tr_imputed[col] = le_info[col].inverse_transform(Tr_imputed[col])
Va_imputed[col] = le_info[col].inverse_transform(Va_imputed[col])
Tr_imputed.isna().sum()
도움이 되셨다면, 광고 한번만 눌러주세요. 블로그 운영에 큰 힘이 됩니다 ^^
728x90
'분석 Python > Data Preprocessing' 카테고리의 다른 글
[변수 선택 및 생성]중요 변수 선택 및 파생 변수 만들기 (2) | 2020.01.08 |
---|---|
[ Python ] Scikit-Learn, 변수 전처리 Pipeline Transformer 만들어보기 (0) | 2019.12.28 |
[변수 처리] 데이터에서 결측치 잘 만들어보기 (0) | 2019.09.17 |
[변수 처리] Python에서 범주형 변수(Categorical) 다루기 (0) | 2019.09.13 |
[ 변수 처리] 파이썬 결측치 대체 알고리즘 비교 예시 (4) | 2019.09.10 |