💡 도움이 되셨다면 ♡와 팔로우 부탁드려요! 미리 감사합니다.
데이터셋에서 특정 값이 존재하지 않거나 누락된 상태를 의미
기본적으로 평균으로 대치하거나 제거하곤 한다.
어떤 방법을 사용하는 것이 옳을까?
→ 결측치에 대해서 도메인 지식이 없으면 정말 위험하다.
다양한 기술적인 방법들은 수치적인 것들만 생각하는 것인데, 도메인보다 더 중요한 것은 없다.
모든 데이터는 데이터에 해당하는 도메인 기반으로 만들어진 것이기 때문이다.
결측치 처리에 크게 두가지가 존재한다.
1. 삭제 (Deletions)
2. 대치 (Imputations)
결측값을 처리하는 다양한 고급 기법을 보여준다.
Sklearn에서 결측치 처리를 위해 제공하는 모듈이 존재하며 다음과 같다.
m
개의 완전한 데이터셋을 만듭니다. 각 대치는 가능한 값의 분포에서 추출된다.m
개의 데이터셋 각각에 대해 분석을 수행하여 모수 추정치와 오차를 계산한다.m
개의 분석 결과를 결합하여 최종 결과를 도출한다. 이를 통해 대치의 불확실성을 줄이고 신뢰성을 높인다.여기서 m
은 사용자거 설정해주는 값으로 3~10 사이로 설정한다.
MICE에서 대치 단계의 단일 iteration이 어떻게 진행되는지 설명하는 예시
Age
를 다시 결측값으로 돌림Income
과 Gender
를 사용해 Age
예측Income
을 다시 결측값으로 돌림Age
와 Gender
로 Income
예측Gender
를 다시 결측값으로 돌림Age
와 Income
을 사용해 Gender
예측이러한 iteration을 m
번 반복하게되면 m
개의 서로 다른 데이터셋이 생성된다.
이후 후속 단계
분석 단계
통합 단계
m
개의 결과 결합하여 최종 추정치를 도출한다.💡 MICE와 Sklearn의 IteartiveImputer의 차이
- MICE : 결측치를 대치하는 서로 다른 데이터셋을 생성하고 분석, 통합 단계를 거쳐 최종 추정치를 도출한다.
- Sklearn의 IterativeImputer : 기본적으로 하나의 예측 모델(BaysianRidge, RandomForestRegressor 등)을 사용해 결측값을 예측한다. 기본적으로 **하나의 데이터셋에서 반복적인 대치 과정을 통해 결측값을 채우고, 최종적으로는 단일 대치 데이터셋만 생성한다. (
분석 단계
,통합 단계
가 생략, 결측값 대치에 집중**)Mice랑 다른 것 같은데 왜 유사하다고 하는걸까?
- 두 방법 모두 결측값을 대치하기 위해 회귀 모델을 사용하여 다른 변수들의 정보를 활용한다는 공통점
- 각 결측값을 예측할 때마다 반복이 진행된다. 즉, 하나의 변수를 대치한 후 그 대치 결과를 기반으로 다른 변수를 예측하는 방식이 두 방법의 공통점
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import SimpleImputer, KNNImputer, IterativeImputer
import statsmodels.api as sm
df = sm.datasets.get_rdataset("AirPassengers", package="datasets").data
# 'time' 컬럼을 datetime 형식으로 변환
df['time'] = pd.date_range(start='1949-01-01', periods=len(df), freq='MS')
df.set_index('time', inplace=True)
df.head()
# 데이터셋 복사
df_sp = df.copy()
# 결측치 구간 범위
nan_ranges = [(5, 15), (30, 40), (55, 65), (90, 110)]
for start, end in nan_ranges:
df.iloc[start:end, :] = np.nan
plt.figure(figsize=(12, 6))
sns.lineplot(data = df, marker='o')
plt.title('Original')
plt.xlabel('Year-Month')
plt.ylabel('Number of Passengers')
plt.show()
# 1차 선형 보간법
df_linear = df.interpolate(method='linear')
# 2차 선형 보간법
df_quadratic = df.interpolate(method='quadratic')
# 평균 대치법
imputer_mean = SimpleImputer(strategy='mean')
df_mean = imputer_mean.fit_transform(df)
df_mean = pd.DataFrame(df_mean, columns = ['value'], index = df.index)
# 0값으로 대치
df_zero = df.fillna(0)
# KNN 방법으로 대치
imputer_knn = KNNImputer(n_neighbors=5)
df_knn = imputer_knn.fit_transform(df)
df_knn = pd.DataFrame(df_knn, columns = ['value'], index = df.index)
# MICE 다중대치법
imputer_mice = IterativeImputer()
df_mice = imputer_mice.fit_transform(df)
df_mice = pd.DataFrame(df_mice, columns = ['value'], index = df.index)
fig, axs = plt.subplots(8,1,figsize=(12,12))
# 그래프를 그리기 전에 결측치 구간 강조
for ax in axs:
for start, end in nan_ranges:
ax.axvspan(df.index[start], df.index[end-1], color='red', alpha=0.3)
sns.lineplot(data= df, marker='o',ax=axs[0], legend='auto')
axs[0].set_title('Original Missing Data')
sns.lineplot(data= df_sp, marker='o',ax=axs[1], legend='auto')
axs[1].set_title('Original Data')
sns.lineplot(data= df_linear, marker='o',ax=axs[2], legend='auto')
axs[2].set_title('Linear')
sns.lineplot(data= df_quadratic, marker='o',ax=axs[3], legend='auto')
axs[3].set_title('quadratic')
sns.lineplot(data= df_mean, marker='o',ax=axs[4], legend='auto')
axs[4].set_title('mean')
sns.lineplot(data= df_zero, marker='o',ax=axs[5], legend='auto')
axs[5].set_title('zero')
sns.lineplot(data= df_knn, marker='o',ax=axs[6], legend='auto')
axs[6].set_title('df_knn')
sns.lineplot(data= df_mice, marker='o',ax=axs[7], legend='auto')
axs[7].set_title('df_mice')
plt.tight_layout()
plt.show()
axvspan
을 사용하여서드로, 수직 범위를 강조 표시, 특정 x축 값의 범위를 강조하여 시각적으로 강조함