1 도입 — 결측은 자료의 일부
거의 모든 실제 자료에 결측 이 있다. 임상시험의 drop-out, 조사의 무응답, A/B 테스트의 비활성 사용자. 결측 처리가 분석 결과를 좌우한다.
2 결측 메커니즘 3 분류 (Rubin 1976)
자료가 왜 결측되는가의 분류.
- MCAR (Missing Completely At Random): 결측이 모든 변수와 무관
- MAR (Missing At Random): 결측이 관측된 변수에 의존 (결측값 자체에는 무관)
- MNAR (Missing Not At Random): 결측이 결측값 자체에 의존
2.1 MCAR — 가장 단순
2.1.1 정의
\[ P(\text{결측} \mid X, Y) = P(\text{결측}) \]
결측이 어떤 변수와도 무관. 단순한 무작위 누락.
2.1.2 사례
- 연구 보조원의 실수 로 자료 누락
- 자료 입력 오류 로 임의 누락
- 기술적 문제 (파일 손상)
2.1.3 처리
- Listwise deletion (결측 행 제거) 가 비편향
- 표본 크기만 줄어듦
- 완전 자료 분석 가능
2.2 MAR — 가장 흔함
2.2.1 정의
\[ P(\text{결측} \mid X, Y) = P(\text{결측} \mid X) \]
결측이 관측된 다른 변수 에 의존. 결측값 자체에는 무관.
2.2.2 사례
- 노년층의 BMI 측정 누락 (연령 정보로 예측 가능)
- 우울증 환자의 일부 척도 항목 미응답 (다른 척도로 추정)
- 모바일 사용자가 데스크톱 자료 결측 (디바이스로 알 수 있음)
2.2.3 처리
- Multiple Imputation (다음 글) 권장
- Listwise deletion 은 편향
- 변수 정보 활용 필수
2.3 MNAR — 가장 어려움
2.3.1 정의
\[ P(\text{결측} \mid X, Y) = P(\text{결측} \mid Y) \]
결측이 결측값 자체에 의존. 직접 모델링 불가.
2.3.2 사례
- 고소득자가 소득 미응답 (소득 자체가 결측 결정)
- 심한 우울증 환자의 측정 누락 (척도 점수 자체가 결정)
- 부정 결과 사용자의 자료 누락 (outcome 자체)
2.3.3 처리
- 민감도 분석 으로 다양한 가정 검토
- 모델 기반 접근 (Selection model, Pattern-mixture model)
- 일반적으로 어려움
임상시험 drop-out 시나리오:
- MCAR: 환자가 우연히 (이사 등) 추적 실패. 결측이 다른 변수와 무관.
- MAR: 연령 많은 환자가 더 자주 추적 실패 (관측된 연령으로 설명 가능).
- MNAR: 처치 효과 없는 환자가 자료 측정 거부 (결측이 outcome 자체에 의존).
A/B 테스트:
- MCAR: 사용자가 기술적 오류 로 자료 미수집. 무작위.
- MAR: 모바일 사용자 가 데스크톱 메트릭 결측 (디바이스 변수로 설명).
- MNAR: 불만족 사용자 가 자료 사용 동의 거부 (만족도 자체가 결측 결정).
대부분 자료가 MAR 또는 MAR + MNAR 혼합. MCAR 은 드물고, 순수 MNAR 도 드물다.
3 결측 진단
3.1 시각적 진단
3.1.1 Missing Pattern Plot
결측 패턴 시각화. 각 행은 자료 점, 각 열은 변수. 결측 셀 표시.
3.1.2 결측률
3.2 형식 진단
3.2.1 Little’s MCAR Test
3.3 MAR vs MNAR 구분
이 둘은 근본적으로 검증 불가능. 결측값을 모르므로 결측이 결측값 자체에 의존하는지 외부 정보 없이는 판단 X.
해법: 민감도 분석. 다양한 가정 (MAR vs 다양한 MNAR 시나리오) 하의 결과 비교.
4 단순 대체 방법
4.1 Method 1 — Listwise Deletion (Complete Case)
결측이 있는 행을 완전 제거.
4.1.1 장점
- 단순
- MCAR 에서 비편향
4.1.2 단점
- MAR 에서 편향
- 표본 크기 손실
- 정보 활용 X
4.1.3 권장
MCAR 가 강하게 의심 + 결측률 5 % 미만에서만 사용.
4.2 Method 2 — Mean Imputation
4.2.1 단점 (모두 심각)
- 분산 과소 추정 (평균 분산 0)
- 상관 관계 약화
- MAR 에서 편향
4.2.2 권장
거의 사용하지 말 것. Multiple imputation 이 항상 더 나음.
4.3 Method 3 — LOCF (Last Observation Carried Forward)
종단 자료에서 마지막 관측값 으로 후속 결측 대체.
예: 환자의 4 주차 측정 결측 → 2 주차 측정값 사용.
4.3.1 사례
임상시험의 drop-out 처리에 자주 사용.
4.3.2 단점
- 변화 무시 (시간에 따른 변화 가정)
- 편향 가능 (drop-out 이 처치 효과와 연관)
- FDA 등 규제 기관도 비판
4.3.3 권장
대안 (MI) 가 가능하면 피하라. 단순함이 장점이지만 정확성 부족.
4.4 Method 4 — Hot Deck Imputation
비슷한 자료점의 값으로 대체.
# 비슷한 연령·성별의 BMI 평균으로 대체
df['bmi'].fillna(df.groupby(['age_group', 'sex'])['bmi'].transform('mean'), inplace=True)4.4.1 장점
- 분포 보존 (mean imputation 보다 나음)
- 상호 의존성 일부 반영
4.4.2 단점
- 변동성 여전히 과소 추정
- “비슷한” 정의 주관적
4.5 Method 5 — Regression Imputation
다른 변수로 회귀 모형 → 결측 예측.
from sklearn.linear_model import LinearRegression
# BMI 결측을 다른 변수로 예측
mask = df['bmi'].isnull()
X_train = df.loc[~mask, ['age', 'sex']]
y_train = df.loc[~mask, 'bmi']
X_test = df.loc[mask, ['age', 'sex']]
model = LinearRegression().fit(X_train, y_train)
df.loc[mask, 'bmi'] = model.predict(X_test)4.5.1 장점
- 변수 관계 활용
- MAR 에서 부분적 편향 보정
4.5.2 단점
- 예측 불확실성 무시 (한 값으로 대체)
- 분산 과소 추정
5 단순 대체의 통합 한계
단순 대체 (single imputation) 의 모든 방법은 결측의 불확실성을 무시.
비유: 모르는 답을 추측한 후 그 추측이 정답인 것처럼 처리. 추측의 불확실성 이 분석 결과에 반영되지 않음.
결과:
- 추정값 은 그럴듯할 수 있음
- 표준 오차 는 과소 추정 (불확실성 무시 때문)
- CI 가 너무 좁음 → false positive 증가
해법: Multiple Imputation (다음 글). 결측을 여러 번 다르게 대체하여 불확실성 반영.
6 결측률과 처리 권장
| 결측률 | 권장 |
|---|---|
| < 5 % | Listwise deletion (MCAR 시) 또는 MI |
| 5 ~ 20 % | Multiple Imputation |
| 20 ~ 50 % | MI + 민감도 분석 |
| > 50 % | 변수 또는 분석 재고 |
7 A/B 테스트의 결측
7.1 흔한 결측 패턴
| 패턴 | 메커니즘 | 처리 |
|---|---|---|
| 노출 안 됨 | 정의상 분석 제외 | OK (무시) |
| 클릭 없음 | 정의상 0 | OK (0 처리) |
| 매출 없음 | 정의상 0 | OK (0 처리) |
| 이탈 사용자 | MAR 또는 MNAR | 신중 |
| 일부 segment 정보 결측 | MAR | MI |
7.2 권장 절차
1. 결측률 확인
2. 패턴 분석 (그룹·시간·변형별)
3. MCAR 가정 검정 (Little's test)
4. 단순 분석 (complete case) + MI 보고
5. 결과 비교 → 일관 여부
8 결측 메커니즘 진단의 자세한 방법
8.1 진단 1 — Missing pattern 시각화
자료 매트릭스의 결측 패턴 을 행렬 시각화. 패턴이 다음 형태일 수 있음:
- Univariate: 한 변수만 결측
- Monotone: 변수 순서로 결측 누적 (longitudinal 자료)
- Arbitrary: 무작위 결측 패턴
8.2 진단 2 — Visualization
missingno 패키지가 결측 시각화 표준:
8.3 진단 3 — Logistic regression of missingness
각 변수의 결측 여부 (이진) 를 다른 변수로 예측:
from sklearn.linear_model import LogisticRegression
# bmi 결측 vs age 의 관계
df['bmi_missing'] = df['bmi'].isnull().astype(int)
mask = ~df['age'].isnull()
X = df.loc[mask, ['age']]
y = df.loc[mask, 'bmi_missing']
if len(np.unique(y)) > 1:
model = LogisticRegression()
model.fit(X, y)
print(f"Coefficient: {model.coef_[0][0]:.4f}")
# 큰 coefficient → MAR (age 가 결측 예측)이 절차로 MCAR vs MAR 부분 검정. MNAR 은 이 방법으로 구분 불가.
9 Listwise Deletion 의 자세한 분석
9.1 MCAR 에서의 비편향성
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
np.random.seed(42)
n = 1000
# 진짜 모형
X = np.random.normal(0, 1, n)
Y = 2 + 3*X + np.random.normal(0, 1, n)
# MCAR 결측 (무작위 30 %)
mcar_missing = np.random.random(n) < 0.30
Y_mcar = Y.copy()
Y_mcar[mcar_missing] = np.nan
# Listwise — 비편향
df_mcar = pd.DataFrame({'X': X, 'Y': Y_mcar}).dropna()
beta_mcar = np.cov(df_mcar['X'], df_mcar['Y'])[0,1] / np.var(df_mcar['X'])
print(f"MCAR + Listwise: β1 = {beta_mcar:.4f} (진짜: 3.0)")
# 약 3.0 (비편향)9.2 MAR 에서의 편향
# MAR 결측 — X 가 큰 경우 더 자주 결측
prob_missing = 1 / (1 + np.exp(-X)) # X 큼 → 결측 확률 큼
mar_missing = np.random.random(n) < prob_missing
Y_mar = Y.copy()
Y_mar[mar_missing] = np.nan
# Listwise — 편향
df_mar = pd.DataFrame({'X': X, 'Y': Y_mar}).dropna()
beta_mar = np.cov(df_mar['X'], df_mar['Y'])[0,1] / np.var(df_mar['X'])
print(f"MAR + Listwise: β1 = {beta_mar:.4f} (진짜: 3.0)")
# 일반적으로 3.0 보다 작음 (큰 X 의 자료 손실로 편향)9.3 함의
MAR 에서 listwise deletion 은 편향 위험. MI 권장.
10 Mean Imputation 의 함정
10.1 분산 과소 추정
# Mean imputation 의 분산 영향
Y_mean_imputed = Y_mar.copy()
mean_observed = np.nanmean(Y_mar)
Y_mean_imputed[np.isnan(Y_mean_imputed)] = mean_observed
print(f"원 자료 분산: {np.var(Y, ddof=1):.4f}")
print(f"결측 후 분산 (관측): {np.nanvar(Y_mar, ddof=1):.4f}")
print(f"Mean imputation 후 분산: {np.var(Y_mean_imputed, ddof=1):.4f}")
# 결측 후 분산보다 mean imputation 분산이 더 작음10.2 상관 약화
# Mean imputation 이 X-Y 상관 약화
corr_orig = np.corrcoef(X, Y)[0,1]
df_listwise = pd.DataFrame({'X': X, 'Y': Y_mar}).dropna()
corr_listwise = np.corrcoef(df_listwise['X'], df_listwise['Y'])[0,1]
X_mi = X.copy()
Y_mi = Y_mar.copy()
Y_mi[np.isnan(Y_mi)] = mean_observed
corr_mi = np.corrcoef(X_mi, Y_mi)[0,1]
print(f"진짜 상관: {corr_orig:.4f}")
print(f"Listwise 상관: {corr_listwise:.4f}")
print(f"Mean imputation 상관: {corr_mi:.4f}")
# Mean imputation 상관이 약화 (결측 자료의 X 정보 무시)이 시뮬레이션이 Mean imputation 의 위험 정량화.
11 A/B 테스트의 결측 처리
11.1 시나리오 — 사용자 segment 결측
import pandas as pd
import numpy as np
# 가상 자료
np.random.seed(42)
n = 5000
df = pd.DataFrame({
'variant': np.random.choice([0, 1], n),
'age_group': np.random.choice(['young', 'mid', 'old'], n),
'tenure_months': np.random.uniform(0, 60, n),
'revenue': np.random.normal(100, 30, n)
})
# 일부 사용자의 segment 정보 결측 (MAR — 신규에서 더 자주)
mask = (df['tenure_months'] < 6) & (np.random.random(n) < 0.30)
df.loc[mask, 'age_group'] = np.nan
# 결측률
print(f"age_group 결측률: {df['age_group'].isnull().mean():.2%}")
# Listwise deletion
df_listwise = df.dropna()
print(f"Listwise 표본: {len(df_listwise)} / {n}")
# 분석 — variant 효과 (Listwise vs Multiple Imputation 비교)
from sklearn.linear_model import LinearRegression
# Listwise
model = LinearRegression()
X = pd.get_dummies(df_listwise[['variant', 'age_group']], drop_first=True)
y = df_listwise['revenue']
model.fit(X, y)
print(f"Listwise variant 효과: {model.coef_[0]:.3f}")이 분석에서 listwise 가 신규 사용자 (tenure 짧음) 를 비례 이상 제외 → variant 효과 추정 편향 가능.
해법: Multiple Imputation (다음 글).
12 후속 — Multiple Imputation
다음 글 A-WOO14-7 은 Multiple Imputation 의 자세한 절차를 다룬다. 결측의 불확실성을 정직하게 반영하는 표준 도구.
13 관련 주제
선행 지식
후속 주제 (Phase A)
- A-WOO14-7 Multiple Imputation
다른 카테고리 연결