[변수 처리] 데이터에서 결측치 잘 만들어보기

2019. 9. 17. 19:57분석 Python/Data Preprocessing

728x90

테스트를 위한 missing data를 만들려고 할 때 수치형 변수는 상관이 없으나 category 변수 같은 경우에는 one hot했을 때도 mssing을 잘 주고 싶어서 시도를 하게 됐다.

지금 해보니 더 쉽게 하는 방법이 있는 것 같은데... 일단 진행을 했으니 공유

No , RAW_Dim = RAW.shape
print(No, RAW_Dim)
p_miss_vec = p_miss * np.ones((No,1)) 
Missing = np.zeros((No,RAW_Dim))
for i in range(RAW_Dim):
    A = np.random.uniform(0., 1., size = [No,])
    B = A > p_miss_vec[i]
    Missing[:,i] = 1.*B
    
missing_RAW = deepcopy(RAW)
missing_RAW[(1-Missing) == 1] = np.nan
missing_RAW2 = missing_RAW.dropna()
missing_RAW.head()

## missing을 제거한 것으로 fitting을 시키고 missing 있는 것으로 transform을 시킵니다.

이것을 했을 때의 가정은 dropna()를 하였을 때 변수가 사라지지 않아야 합니다.

ce_one_hot = ce.OneHotEncoder(cols=obj_col , use_cat_names=True )
ce_one_hot.fit(X = missing_RAW2)
result = ce_one_hot.transform(missing_RAW)
result.head(20)

해당 함수를 이용해 노란색 부분은 다 nan로 바꿔주고 그리고 그다음 missing matrix를 구해봅니다.

def nan_remove(result ,  obj_col ) :
    dict_ = {}
    for colum in obj_col :
        dict_[colum] = []    
    transform_col = result.columns.tolist()
    for colum in obj_col :
        for ck in transform_col :
            if re.search("{}_".format(colum) , ck) :
                dict_[colum].append(ck) 
    for key , value in dict_.items() :
        mis_idx = result2[value][result2[value].sum(axis = 1) == 0].index.tolist()
        ddd = [idx for idx , nn in enumerate(pd.Series(transform_col).isin(value).values.tolist()) if nn == True ]
        result2.iloc[mis_idx , ddd ] = result2.iloc[idx , ddd ].replace(0, np.nan)
    missing_matrix = result2.isna().replace({False : 0 , True : 1})
    return result2 , dict_ , missing_matrix
result2 , obj_info_dict , missing_matrix = nan_remove(result , obj_col)
result2.head()

missing_matrix


위의 것에서는 dropna()를 하는 부분에서 문제가 발생하는 것을 확인

아래 코드가 더 쉽게 가능한 것 같다.


start_idx = 0
store = []
for idx , col in enumerate(usecols) :
    if col in obj_col :
        nn = RAW[col].nunique()
        aa = [start_idx , start_idx + nn]
        start_idx += nn
        store.append(aa)
    else :
        aa = [start_idx , start_idx +1]
        store.append(aa)
        start_idx += 1
        
No , _ = RAW.shape
RAW_Dim = store[-1][1]
p_miss_vec = p_miss * np.ones((No,1)) 
Missing = np.zeros((No,RAW_Dim))
for st in store :
    len_ = st[1] -st[0]
    A = np.random.uniform(0., 1., size = [No,1])
    B = A > p_miss_vec
    Missing[:,st[0]:st[1]] = 1.* np.tile(B , (len_))
ce_one_hot = ce.OneHotEncoder(cols=obj_col , use_cat_names=True )
ce_one_hot.fit(X = RAW)
result = ce_one_hot.transform(RAW)
result.head()
missing_RAW = deepcopy(result)
missing_RAW[(1-Missing) == 1] = np.nan
missing_RAW.head(10)

 

728x90