다중 대체 — PMM·Normal Imputation 의 메커니즘과 적용 (Buisson Ch.6.3)

Multiple Imputation 의 m 번 대체, Rubin’s Rules, mice 패키지 활용

Buisson (2021) Ch.6 의 Multiple Imputation 절을 자세히 정리한다. 단일 대체의 한계, m 번 대체로 결측 불확실성 표현, Predictive Mean Matching (PMM) 과 Normal Imputation 의 차이, mice 패키지의 호출 방법, deterministic MNAR (Neuro 의 임계값 결측) 의 특수 처리를 단계별로 시연한다.

Experimentation
Causal Inference
저자

Kwangmin Kim

공개

2026년 05월 08일

1 정의

정의: Multiple Imputation (MI)

결측 값을 단일 값으로 대체하지 않고, m 번 다른 대체 데이터셋을 생성한 후, 각 데이터셋에 분석을 적용하고 Rubin’s rules 로 결과 종합 (Buisson, 2021, Ch.6; Rubin, 1987).

절차:

원본 데이터 (결측 있음)
       ↓ (대체 모형 적용 m 번)
대체 1, 대체 2, ..., 대체 m   (각각 완전 데이터셋)
       ↓ (각각 분석)
결과 1, 결과 2, ..., 결과 m
       ↓ (Rubin's rules 로 종합)
최종 추정량 + 신뢰구간

권장 m: 5~50. 결측 비율이 높을수록 더 많은 m.

직관 — MI 의 4 가지 목적

분석가가 MI 를 사용하는 이유:

  1. 편향 제거: MAR 가정 하 listwise deletion 의 편향 보정
  2. 불확실성 반영: 결측에 대한 지식 부족이 신뢰구간에 반영
  3. 표본 크기 보존: 결측 행 제거 안 함 → 통계적 검정력 유지
  4. 분석 일관성: 모든 변수에 같은 표본 사용 → 회귀 비교 가능

이 4 가지가 MI 가 표준 도구인 이유. listwise/mean 어느 것도 4 모두 충족 못함.

→ 약간의 추가 비용 (m 번 분석) 으로 분석 품질 큰 향상.

2 단일 대체의 한계 (재방문)

단일 대체가 안 되는 이유 — 통계적 근거

단일 대체 방법:

  • Mean imputation: 결측을 평균으로
  • Regression imputation: 다른 변수로 회귀 → 예측값으로 대체
  • Hot-deck imputation: 비슷한 사람의 값으로 대체

문제: 결측의 불확실성이 무시됨.

수식으로:

\[ \text{Var}(\hat{\theta})_{\text{single}} = \text{Var}(\hat{\theta} \mid X_{\text{filled}}) \quad \text{(결측 불확실성 부재)} \]

진짜 분산:

\[ \text{Var}(\hat{\theta})_{\text{true}} = \underbrace{\text{Var}(\hat{\theta} \mid X_{\text{filled}})}_{\text{within (조건부)}} + \underbrace{\text{Var}_{X_{\text{missing}}}(\hat{\theta})}_{\text{between (결측 변동)}} \]

단일 대체는 within 만 측정. between 무시 → 분산 과소 추정.

직관 — Within vs Between 의 비유

비유: 4 인 패널 회의의 의사결정.

  • 단일 대체 = 한 사람의 의견만 들음. 다른 3 명의 의견 모름. 의사결정의 진짜 불확실성 모름.
  • 다중 대체 = 4 명 모두 다른 시점에 의견 → 의견 분포 (= between 분산) 가 의사결정 불확실성 반영.

분석에서:

  • 단일 대체 = 결측에 한 가능성만 가정. 신뢰 가짜 ↑.
  • 다중 대체 = 결측의 여러 가능성. 신뢰의 진짜 폭 측정.

→ 다중 대체는 정직함의 도구. 결측의 무지를 분산으로 표현.

3 Multiple Imputation 의 절차

3.1 단계 1: 대체 모형 적합

대체 모형의 의미

대체 모형: 결측 변수 를 다른 변수에 대해 회귀한 모형.

수식:

\[ X_{\text{missing}} \mid X_{\text{observed}}, Y, Z \sim \text{Distribution}(\theta) \]

이 모형으로 결측 값을 예측 + sampling.

종류:

  • Normal: 수치 변수 → 정규 분포로 sampling
  • PMM (Predictive Mean Matching): 가까운 관측값으로 대체
  • Logistic: 이진 변수 → 베르누이로 sampling
  • Polytomous: 범주 변수 → 다항 분포

mice 패키지가 변수 유형 자동 감지 + 적절한 모형 선택.

3.2 단계 2: m 번 대체

직관 — 왜 여러 번?

한 번 대체:

  • 한 가능한 결측 값만 사용
  • 결측 불확실성 반영 안 됨

m 번 대체:

  • 매번 다른 sampling → 다른 결측 값
  • m 개 데이터셋의 결과 분포가 결측 불확실성 반영

m 의 선택:

  • m = 5: 빠르지만 부정확
  • m = 20: 표준 권장 (Rubin 의 효율성 분석)
  • m = 100: 결측 비율 높을 때 (50%+)

비즈니스 분석에서 m = 5~20 이 일반적.

3.3 단계 3: 각 데이터셋 분석

동일 분석 m 번 적용

각 대체 데이터셋에 같은 회귀·검정·요약을 적용.

대체 1 → 분석 1 (점추정 θ_1, SE_1)
대체 2 → 분석 2 (점추정 θ_2, SE_2)
...
대체 m → 분석 m (점추정 θ_m, SE_m)

각 결과의 점추정 + 표준 오차 저장.

3.4 단계 4: Rubin’s Rules 종합

종합 공식

점추정 (Pooled Estimate):

\[ \bar{\theta} = \frac{1}{m} \sum_{i=1}^{m} \theta_i \]

(평균)

Within-imputation 분산:

\[ \bar{U} = \frac{1}{m} \sum_{i=1}^{m} \text{SE}_i^2 \]

Between-imputation 분산:

\[ B = \frac{1}{m-1} \sum_{i=1}^{m} (\theta_i - \bar{\theta})^2 \]

Total 분산:

\[ T = \bar{U} + \left(1 + \frac{1}{m}\right) B \]

Pooled SE:

\[ \text{SE}_{\text{pooled}} = \sqrt{T} \]

직관 — Rubin’s Rules 의 통계적 의미

Within (\(\bar{U}\)):

  • 각 대체 내의 표본 잡음
  • “이 대체 데이터에 진짜 분석을 적용했을 때의 잡음”

Between (\(B\)):

  • m 개 대체 사이의 변동
  • “결측을 다르게 채웠을 때 결과가 얼마나 흔들리는가”
  • 이게 결측 불확실성

Total = within + (1 + 1/m) × between:

  • 두 분산의 합
  • (1 + 1/m) 보정은 m 이 작을 때 between 의 추정치가 underestimate 되는 것 보정
  • m → ∞ 시 (1 + 1/m) → 1

→ 두 잡음 원천을 정확히 결합. 분산이 listwise 보다 약간 크지만 진짜 불확실성에 가까움.

직관 — Pooled CI 의 자유도

t-분포의 자유도도 Rubin 이 제시:

\[ \nu = (m - 1) \left( 1 + \frac{\bar{U}}{(1 + 1/m) B} \right)^2 \]

이 자유도는 결측 비율에 따라:

  • 결측 적음 → \(\nu\) 큼 (정규 분포 근사)
  • 결측 많음 → \(\nu\) 작음 (t-분포의 두꺼운 꼬리)

신뢰구간:

\[ \bar{\theta} \pm t_{\nu, 0.975} \cdot \text{SE}_{\text{pooled}} \]

비즈니스 분석에서: 결측이 많을수록 신뢰구간이 넓음 — 정직한 신호.

4 PMM — Predictive Mean Matching

4.1 정의

PMM 의 작동

PMM 은 결측 값을 비슷한 관측 값으로 대체.

절차:

Step 1: 결측 변수 X 를 다른 변수에 대해 회귀 → 예측 모형 β̂
Step 2: 결측 행에 대한 예측값 X̂_missing 계산
Step 3: 관측 행 중에서 X̂_missing 과 가장 비슷한 예측값을 가진 k 개 선택
Step 4: 그 k 개의 실제 X 값 중 무작위로 하나 sampling → 결측 대체

k = 5 가 일반적.

직관 — PMM 이 좋은 이유

PMM 의 강점:

  1. 분포 보존: 대체 값이 항상 관측된 값에서 유래 → 변수의 진짜 분포 유지
  2. 외삽 회피: 회귀의 예측값을 직접 사용하지 않음 → 비현실적 값 (예: 음의 나이) 안 나옴
  3. 비선형 패턴: 회귀 모형이 부정확해도 비슷한 관측값을 찾음 → robust
  4. 범주 호환: Binary, integer, 등 자연스럽게 처리

단점:

  1. 외삽 부재: 관측 데이터의 범위 밖 결측은 처리 어려움
  2. k 개 후보 선택: 작은 표본에서 적절한 후보 부족 가능
  3. 계산 비용: 각 결측마다 distance 계산

비즈니스 분석에서 PMM 이 default. 단순하고 robust.

4.2 PMM 의 예시

단계별 시연

가상 데이터 — Income 결측, Age 와 Education 관측:

관측 데이터:
  Age   Edu   Income
   25   B.S.   60K
   30   M.S.   80K
   35   B.S.   70K
   40   PhD    120K
   45   M.S.   100K

결측 행:
  Age   Edu   Income
   33   M.S.   ???

Step 1: Income ~ Age + Edu 회귀 → β̂

Step 2: 결측 행 예측값: \(\hat{X}_{missing} = \hat{\beta}_0 + \hat{\beta}_{age} \cdot 33 + \hat{\beta}_{edu_{MS}} = 85K\) (예시)

Step 3: 관측 행의 예측값 계산: - Row 1: 55K (예측) - Row 2: 78K - Row 3: 65K - Row 4: 110K - Row 5: 95K

가장 가까운 5 개 (k=5) 중에서 후보: - Row 2 (78K), Row 5 (95K) — 가까움

Step 4: Row 2 와 Row 5 중 무작위 선택 → 80K 또는 100K 로 대체.

직관 — PMM 의 매력

PMM 의 키 통찰: 회귀로 예측, 관측값으로 대체.

  • 회귀 모형이 비선형 패턴을 놓쳐도, 가까운 관측값이 그 패턴을 보존
  • “33세 M.S. 의 진짜 Income 은 80K 또는 100K 일 것” 이라는 직관적 결과

비유: 아파트 가격 추정 — 회귀로 예측 (85K) 하지만, “비슷한 가격대 실제 거래” (80K 또는 100K) 가 더 신뢰 가능.

이게 PMM 이 부동산·소득·만족도 등 분포가 복잡한 변수에 잘 맞는 이유.

5 Normal Imputation

정의

Normal imputation: 결측 변수가 정규 분포 따른다고 가정 → 회귀 모형에서 예측 + 정규 분포 잡음 추가.

절차:

Step 1: X ~ Y + Z 회귀 → β̂, σ̂²
Step 2: 결측 행 예측: X̂_missing = β̂_0 + β̂_y Y + β̂_z Z
Step 3: 잡음 추가: X_imputed = X̂_missing + ε,  ε ~ N(0, σ̂²)
직관 — Normal vs PMM 의 차이

Normal:

  • 결측 변수의 분포 가정 (정규)
  • 외삽 가능 (관측 데이터 범위 밖 값 가능)
  • 회귀 모형의 정확성에 의존

PMM:

  • 분포 가정 없음
  • 외삽 불가
  • 회귀 모형이 부정확해도 robust

선택 기준:

  • 정규 분포 확신 + 외삽 필요 → Normal
  • 분포 모름, 보수적 선호 → PMM (default)

비즈니스에서: PMM 이 일반적 선택. Normal 은 통계학자가 분포 검증 후.

5.1 Normal 의 예시

단계별 시연

같은 가상 데이터로 Normal 시연.

Step 1: Income ~ Age + Edu 회귀 → β̂, σ̂² = 100 (예시)

Step 2: 결측 행 예측 = 85K

Step 3: 잡음 추가:

\[ X_{imputed} = 85 + \epsilon, \quad \epsilon \sim N(0, 100) \]

m 번 sampling:

  • 대체 1: \(\epsilon_1 = 5\) → 90K
  • 대체 2: \(\epsilon_2 = -8\) → 77K
  • 대체 3: \(\epsilon_3 = 12\) → 97K
  • 대체 4: \(\epsilon_4 = 0\) → 85K
  • 대체 5: \(\epsilon_5 = -15\) → 70K

PMM 과 달리 정확히 관측값일 필요 없음. 회귀 잡음만 추가.

6 AirCnC — MI 적용

6.1 단계 1: 대체 모형 정의

R / Python 코드

R (mice 패키지):

library(mice)

# 5 번 대체, default 방법 (PMM 자동 선택)
imp <- mice(available_data, m = 5, seed = 42)

# 대체 데이터셋 추출
imputed_data <- complete(imp, 1)  # 첫 대체

Python (statsmodels.imputation.mice):

from statsmodels.imputation import mice as mi

imp_data = mi.MICEData(available_data)

# m 번 update
m = 5
for _ in range(m):
    imp_data.update_all()

mice 가 변수 유형 자동 감지:

  • 수치 변수 → PMM
  • Binary 변수 → Logistic
  • 범주 변수 → Polytomous logit

6.2 단계 2: 각 대체에 회귀 적합

import statsmodels.api as sm

# m 개 대체 데이터셋 생성
imputed_dfs = []
for _ in range(5):
    imp_data.update_all()
    imputed_dfs.append(imp_data.data.copy())

# 각 대체에 회귀
results = []
for i, df_imp in enumerate(imputed_dfs):
    X = sm.add_constant(df_imp[["age", "open", "extra", "neuro"]])
    m_i = sm.OLS(df_imp["bkg_amt"], X).fit()
    results.append({
        "imputation": i,
        "beta_extra": m_i.params["extra"],
        "se_extra": m_i.bse["extra"],
        "beta_neuro": m_i.params["neuro"],
        "se_neuro": m_i.bse["neuro"],
    })

6.3 단계 3: Rubin’s Rules

def rubin_pooling(estimates, ses, m=None):
    """Rubin's rules 로 추정량 종합."""
    estimates = np.array(estimates)
    ses = np.array(ses)
    if m is None:
        m = len(estimates)

    theta_bar = np.mean(estimates)
    U_bar = np.mean(ses ** 2)
    B = np.var(estimates, ddof=1)
    T = U_bar + (1 + 1/m) * B
    se_pooled = np.sqrt(T)

    # 자유도
    nu = (m - 1) * (1 + U_bar / ((1 + 1/m) * B)) ** 2 if B > 0 else float("inf")

    return theta_bar, se_pooled, nu


# Extra 의 종합
betas = [r["beta_extra"] for r in results]
ses = [r["se_extra"] for r in results]
theta, se, nu = rubin_pooling(betas, ses)

# t-분포 신뢰구간
from scipy.stats import t as t_dist
ci_lo = theta - t_dist.ppf(0.975, nu) * se
ci_hi = theta + t_dist.ppf(0.975, nu) * se

print(f"Extra: beta = {theta:.3f}, SE = {se:.3f}, df = {nu:.1f}")
print(f"  95% CI: [{ci_lo:.3f}, {ci_hi:.3f}]")
직관 — Rubin Pooling 결과의 특징

비교 (가상 결과):

방법 \(\beta_{extra}\) SE 95% CI
Listwise 8.2 1.5 [5.3, 11.1]
Mean impute 6.1 0.8 [4.5, 7.7] (가짜 정확)
MI (m=5) 9.5 1.8 [5.9, 13.1]

MI 가:

  • 점추정이 진짜에 가깝게 (편향 보정)
  • SE 가 listwise 보다 약간 큼 (결측 불확실성 반영)
  • 신뢰구간이 적절히 넓음 (정직한 불확실성)

→ MI 가 두 종류의 잘못 (listwise 의 편향, mean 의 가짜 정확) 모두 회피.

7 Deterministic MNAR 의 특수 처리

Buisson 의 발견 — Neuro 의 특이 패턴

AirCnC Neuroticism 의 분포 (히스토그램):

  • 0~3: 다양한 빈도
  • 4: 0 명 (전혀 없음)
  • 5: 매우 많음
  • 6~10: 정상적 빈도

이 패턴이 보여주는 것:

  • Neuroticism 4 인 사람들이 모두 결측
  • Threshold 에서 결측이 시작
  • Deterministic MNAR: 진짜 값이 임계값 ≤ 4 면 결측, > 4 면 관측
직관 — 임계값 결측의 비즈니스 사례

“Determinstic MNAR” 의 흔한 사례:

  • GPA 임계값: 면접 받은 후보의 GPA > 3.0 만 → InterviewScore 가 GPA > 3.0 만 관측
  • 소득 신고: 일정 소득 이상만 신고 의무 → 낮은 소득은 모두 결측
  • 임상 데이터: Lab 값이 정상 범위 안이면 기록 안 함, 비정상만 기록 → 정상 값 결측
  • 시스템 로그: 임계 이상 이벤트만 로깅 → 작은 이벤트 결측

이런 패턴은 비즈니스 룰 의 흔한 결과. 도메인 인터뷰가 진단 핵심.

표준 MI 가 작동 안 하는 이유

Deterministic MNAR 의 어려움:

  • 결측 데이터의 진짜 값이 알려진 범위 (≤ 4) 에 있음
  • mice 의 default PMM 은 관측 데이터에서 sampling
  • 관측 데이터에 ≤ 4 값이 없음 → 대체 값도 ≤ 4 안 됨
  • 편향 큰 결과

특수 처리 필요:

  1. 임계값 정보를 명시적으로 활용 (예: 결측 = ≤ 4 라고 가정)
  2. Truncated normal distribution 으로 sampling
  3. Sensitivity analysis (다양한 임계값 가정)
직관 — 외부 정보의 활용

Deterministic MNAR 의 처리:

  • 도메인 정보: “Neuro 4 인 사람은 모두 결측”
  • 결측 값을 0~4 범위로 sampling (관측 데이터의 분포 외삽)
  • 또는 Tobit-like 모형 (censored regression) 사용

이 경우 분석가가 가정해야 할 것 (외부 정보 없으면):

  • “결측된 사람들의 진짜 분포는 0~4 의 균등?”
  • “정규 분포의 절단 (truncated)?”

각 가정 하 분석 → sensitivity. 결과의 안정성 점검.

8 응용 — 비즈니스 사례

8.1 이메일 캠페인 분석

결측 처리 워크플로

분석 질문: “이메일 캠페인이 매출을 늘리는가?”

데이터:

  • 모든 고객 ID, demographics (관측)
  • 이메일 열람 여부 (관측)
  • 클릭 (이메일 안 받은 사람 결측)
  • 구매 (모두 관측)

결측 (Click): MAR — 이메일 받은 사람만 클릭 가능 → 받음 여부에 의존.

처리:

  1. mice 로 클릭 결측 PMM 대체
  2. 5 개 대체 데이터셋 → 회귀 5 번
  3. Rubin pooling

결과: 캠페인 효과의 정확한 추정 + 진짜 신뢰구간.

8.2 의료 데이터 분석

임상 시험 결측

분석 질문: “약물 X 가 6 개월 후 outcome 을 개선하는가?”

데이터:

  • 환자 baseline (관측)
  • Treatment 배정 (관측)
  • 6 개월 outcome (10% 결측, loss to follow-up)

결측 (Outcome): MAR 또는 MNAR.

처리:

  1. MI (m = 50, 결측 비율 작아 충분)
  2. 각 대체에 회귀
  3. Pooled estimate + CI

CONSORT 의무: 결측 처리 명시 + 가정 명시.

9 코드 예시 — Python 으로 MI 시뮬레이션

9.1 단순 MI 구현 (PMM)

import numpy as np
import pandas as pd
import statsmodels.api as sm
from sklearn.neighbors import NearestNeighbors

def simple_pmm(df, target_col, predictor_cols, k=5):
    """PMM 한 번 적용."""
    df = df.copy()
    obs_mask = df[target_col].notna()
    miss_mask = ~obs_mask

    if miss_mask.sum() == 0:
        return df

    # 회귀 적합
    X_obs = df.loc[obs_mask, predictor_cols].values
    y_obs = df.loc[obs_mask, target_col].values

    X_obs_const = sm.add_constant(X_obs)
    model = sm.OLS(y_obs, X_obs_const).fit()

    # 모든 행의 예측값
    X_all = sm.add_constant(df[predictor_cols].values)
    pred_all = model.predict(X_all)

    # 결측 행의 예측값 ↔ 관측 행의 예측값 매칭
    pred_obs = pred_all[obs_mask]
    pred_miss = pred_all[miss_mask]

    nn = NearestNeighbors(n_neighbors=k)
    nn.fit(pred_obs.reshape(-1, 1))
    _, indices = nn.kneighbors(pred_miss.reshape(-1, 1))

    # k 개 후보 중 무작위 선택
    chosen = np.array([y_obs[idx[np.random.randint(k)]] for idx in indices])
    df.loc[miss_mask, target_col] = chosen

    return df


def multiple_imputation(df, target_col, predictor_cols, m=5, k=5):
    """m 번 PMM 적용."""
    return [simple_pmm(df, target_col, predictor_cols, k=k) for _ in range(m)]
직관 — 단순 PMM 의 작동

이 코드의 단계:

  1. 회귀 모형 적합 (관측 데이터로)
  2. 모든 행의 예측값 계산
  3. 결측 행의 예측값과 가장 가까운 k 개 관측 행 찾기
  4. 그 k 개의 실제 값 중 무작위 선택

sklearnNearestNeighbors 가 nearest 매칭 자동.

이게 mice 패키지의 PMM 구현 핵심. 매우 단순하지만 효과적.

9.2 시뮬레이션 — 진짜 vs MI 비교

np.random.seed(42)
n = 2000

# 완전 데이터 (ground truth)
age = np.random.normal(40, 12, n).clip(18, 80)
extra = np.random.normal(5, 2, n).clip(0, 10)
true_beta_age = 5
true_beta_extra = 10
bkg_amt = (
    true_beta_age * age + true_beta_extra * extra
    + np.random.normal(500, 100, n)
).clip(0, 2000)

complete_df = pd.DataFrame({
    "age": age, "extra": extra, "bkg_amt": bkg_amt,
})

# MAR 결측 (extra 가 age 에 의존)
miss_prob = 1 / (1 + np.exp(-(0.05 * (age - 50))))
miss_mask = np.random.uniform(0, 1, n) < miss_prob
miss_df = complete_df.copy()
miss_df.loc[miss_mask, "extra"] = np.nan

print(f"결측 수: {miss_mask.sum()} ({miss_mask.mean()*100:.1f}%)")

# 1. Listwise deletion
listwise_df = miss_df.dropna()
m_lw = sm.OLS(listwise_df["bkg_amt"], sm.add_constant(listwise_df[["age", "extra"]])).fit()

# 2. Mean imputation
mean_df = miss_df.copy()
mean_df["extra"] = mean_df["extra"].fillna(mean_df["extra"].mean())
m_mean = sm.OLS(mean_df["bkg_amt"], sm.add_constant(mean_df[["age", "extra"]])).fit()

# 3. Multiple Imputation (m=5)
imputed = multiple_imputation(miss_df, "extra", ["age", "bkg_amt"], m=5)
mi_results = []
for df_imp in imputed:
    m_i = sm.OLS(df_imp["bkg_amt"], sm.add_constant(df_imp[["age", "extra"]])).fit()
    mi_results.append({
        "beta_extra": m_i.params["extra"],
        "se_extra": m_i.bse["extra"],
    })

mi_pooled, mi_se, mi_df = rubin_pooling(
    [r["beta_extra"] for r in mi_results],
    [r["se_extra"] for r in mi_results],
)

# 4. 완전 데이터 (ground truth 비교용)
m_true = sm.OLS(complete_df["bkg_amt"], sm.add_constant(complete_df[["age", "extra"]])).fit()

print("\n=== Beta Extra 비교 ===")
print(f"  진실 (완전): {m_true.params['extra']:.3f} (SE = {m_true.bse['extra']:.3f})")
print(f"  Listwise:    {m_lw.params['extra']:.3f} (SE = {m_lw.bse['extra']:.3f})")
print(f"  Mean impute: {m_mean.params['extra']:.3f} (SE = {m_mean.bse['extra']:.3f})")
print(f"  MI (5):      {mi_pooled:.3f} (SE = {mi_se:.3f})")
직관 — 시뮬레이션 결과 해석

예상:

방법 β SE 진실과 차이
진실 10.0 0.4 0
Listwise 9.2 0.6 0.8
Mean impute 5.5 0.4 (가짜) 4.5
MI (5) 9.8 0.5 0.2

Mean imputation 이 가장 큰 편향. MI 가 진실에 가장 가까움.

→ MI 의 우월성을 직접 확인. 추가 비용은 작고 (m 번 분석), 효과는 큰.

9.3 진단 — Imputation 분포 점검

def imputation_diagnostics(complete_df, imputed_dfs, target_col):
    """대체 결과의 분포가 합리적인지 점검."""
    obs_values = complete_df[target_col].dropna()

    fig, axes = plt.subplots(1, len(imputed_dfs) + 1, figsize=(15, 4), sharey=True)

    # 관측 분포
    axes[0].hist(obs_values, bins=20, color="lightblue")
    axes[0].set_title(f"Observed ({len(obs_values)})")

    # 각 대체 분포
    for i, df_imp in enumerate(imputed_dfs):
        axes[i + 1].hist(df_imp[target_col], bins=20, color="lightgreen")
        axes[i + 1].set_title(f"Imputation {i+1}")

    plt.tight_layout()
    plt.savefig("imputation_diag.png", dpi=80)
    plt.show()


import matplotlib.pyplot as plt
imputation_diagnostics(miss_df, imputed, "extra")
직관 — 분포 점검의 의미

분석가가 imputation 의 출력을 점검하는 이유:

  • 대체 분포가 관측 분포와 비슷한가? (PMM 은 자동 보장)
  • 이상한 값 (예: 음수, 매우 큰 값) 이 들어왔는가?
  • m 개 대체 사이 분포 변동 큰가? (결측 불확실성 큰 신호)

만약 분포가 이상하면:

  • 회귀 모형 재검토
  • PMM 의 k 조정
  • 다른 imputation 방법 시도

이 점검이 imputation 의 자기 검증.

10 권장 사항

분석가의 default
  1. 변수 유형 따라 자동 선택: mice 의 default 사용
  2. m = 5~20: 결측 비율이 낮으면 5, 높으면 20
  3. 회귀 모형 검증: 대체 후 회귀 결과의 분포 점검
  4. Sensitivity analysis: m 을 5, 10, 20 변경 → 결과 안정성 점검
  5. 보고서 명시: “MI (mice, m=10) 으로 처리. MAR 가정. MNAR 의심 시 sensitivity analysis 실시.”

이 default 가 비즈니스 분석의 표준.

11 관련 주제

11.1 Ch.6 의 형제 글

11.2 후속 챕터

11.4 카테고리 진입점

Subscribe

Enjoy this blog? Get notified of new posts by email: