Case-Control 설계와 분석 방법 — OR·MH·Logistic

Woodward Ch.6.1~6.2 — Design & Analysis Methods

Cumulative case-control 의 설계 정의, OR 의 수식적 산출, Mantel-Haenszel stratification, logistic regression 까지 분석 도구의 통계적 정당화를 추상 → 일상어 → 반사실 3 단계 직관으로 풀어낸다. 신뢰구간 산출과 표본 크기 계산도 함께 정리한다.

Experimentation
Epidemiology
저자

Kwangmin Kim

공개

2026년 05월 08일

1 6.1 Design — 설계의 통계적 정의

정의: Cumulative Case-Control

연구 종료 시점에 결과 발생자 \(n_1\) 명과 미발생자 \(n_0\) 명을 각각 표집. 각 군에서 과거 노출 분포를 측정.

수식 표기: - \(a\): 노출 cases - \(b\): 비노출 cases - \(c\): 노출 controls - \(d\): 비노출 controls

진성 분포: \[ P(X=1 \mid Y=1), \quad P(X=1 \mid Y=0) \]

이 두 conditional probability 만 자료에서 추정 가능. 마진 \(P(Y=1)\)표집 비율로 결정 되어 자료에서 추정 불가.

3 단계 직관:

  • 추상: Marginal P(Y) 정보가 표집에 의해 인위적 — 자연 발생률 아님. Conditional 로만 추정 가능한 양에 의존.
  • 일상어 비유: 합격자 100 명 + 불합격자 100 명을 인위 표집. “전체 응시자 중 합격률” 은 추정 불가, “합격자의 X 비율” 은 추정 가능.
  • 반사실: Cohort 는 표집이 노출 기준이라 P(Y) 추정 가능 → RR 직접 산출.

2 6.2 Analysis Methods

2.1 Method 1 — Crude OR

\[ \hat{\text{OR}} = \frac{ad}{bc} \]

\(\log \hat{\text{OR}}\) 의 표준오차 (대표본 Wald): \[ \text{SE}(\log \hat{\text{OR}}) = \sqrt{\frac{1}{a} + \frac{1}{b} + \frac{1}{c} + \frac{1}{d}} \]

95% Wald CI: \[ \exp\left( \log \hat{\text{OR}} \pm 1.96 \cdot \text{SE} \right) \]

직관 3 단계: SE 의 합산 구조
  • 추상: \(\log \hat{\text{OR}} = \log a - \log b - \log c + \log d\). 각 항의 분산이 \(1/n_{\text{cell}}\) 으로 근사 → 합산.
  • 일상어 비유: 4 가지 측정값의 합산 결과의 분산은 각 분산의 합. 작은 셀이 큰 분산 (1/n) → 전체 SE 의 주된 source.
  • 반사실: 한 셀이 매우 작으면 (예: \(a = 1\)) SE 폭증 → CI 가 매우 wide. Sample 보강 또는 exact 방법 (Fisher) 필요.

2.2 Method 2 — Mantel-Haenszel Stratification

정의: MH Estimator

각 stratum \(s\) 의 sub-table:

Exposed Unexposed
Cases \(a_s\) \(b_s\)
Controls \(c_s\) \(d_s\)

총합 \(n_s = a_s + b_s + c_s + d_s\).

\[ \hat{\text{OR}}_{\text{MH}} = \frac{\sum_s (a_s d_s) / n_s}{\sum_s (b_s c_s) / n_s} \]

2.3 MH 의 가중

직관: 왜 \(a_s d_s / n_s\) 형태인가
  • 추상: 각 stratum 의 OR 정보의 양은 \(a_s d_s / n_s\)\(b_s c_s / n_s\). 작은 stratum 의 정보 ↓.
  • 일상어 비유: 학교별 평균 점수의 가중 평균 — 큰 학교 + 균형 잡힌 분포의 가중 ↑.
  • 반사실: 단순 평균은 작은 stratum 에 과한 가중. MH 가 정보량 기반 가중.

2.4 Breslow-Day 검정 — Effect Modification

Strata 간 OR 동질성 검정.

\(H_0\): 모든 strata 의 OR 가 동일.

기각이면 effect modification → strata 별 OR 별도 보고.

가정 위반: Effect Modification 무시

가설: 흡연-폐암 OR 가 남성 5, 여성 8 로 다름. MH 가 둘을 가중 평균하여 OR 6.5 로 보고 → “흡연이 남녀 모두에게 같은 효과” 로 오역.

3 단계 직관:

  • 추상: \(\text{OR}(s)\) 가 stratum 의 함수면 단일 OR 는 정보 손실.
  • 일상어 비유: 두 학년의 시험 평균이 다른데 전체 평균만 보고. 학년별 차이를 못 봄.
  • 반사실: Breslow-Day 검정 → 동질성 점검. 기각 시 strata 별 OR 보고 + interaction 항 모형화.

2.5 Method 3 — Logistic Regression

가장 일반적 분석.

\[ \text{logit}(P(Y=1 \mid X, \mathbf{Z})) = \beta_0 + \beta_X X + \boldsymbol{\beta}_Z^T \mathbf{Z} \]

$(_X) = $ Z 보정된 OR.

2.6 Logistic vs MH 의 일관성

직관: 두 방법의 동치
  • 추상: 단일 binary confounder + 큰 sample 이라면 MH 와 logistic regression 거의 동일 OR 산출.
  • 일상어 비유: 두 가지 평균 도구로 같은 자료의 평균을 계산하면 작은 차이 있을 뿐 큰 흐름 일치.
  • 반사실: 다중 confounder + 연속 변수 + 상호작용은 logistic 만 유연. MH 는 셀이 비면 작동 어려움.

2.7 Sample Size 계산

정의: Case-Control Sample Size

Type I error \(\alpha\), Type II error \(\beta\), 노출 prevalence \(p_0\) (controls), 검출하고자 하는 OR \(\Psi\) 를 위해 필요한 control:case 비율 \(c\).

대표본 근사 (1:1): \[ n_{\text{cases}} = \frac{(z_{\alpha/2} + z_\beta)^2 \cdot 2 \bar{p}(1 - \bar{p})}{(p_1 - p_0)^2} \]

여기서 \(p_1 = \frac{\Psi p_0}{1 + (\Psi - 1) p_0}\), \(\bar{p} = (p_0 + p_1) / 2\).

직관 3 단계: Sample Size 의 결정 변수
  • 추상: \(n \propto (z_{\alpha/2} + z_\beta)^2 / (\text{effect size})^2\). 효과가 작을수록 표본 ↑.
  • 일상어 비유: 두 그룹의 키 차이가 1cm 면 큰 표본 필요, 10cm 면 적은 표본도 충분.
  • 반사실: 검출하고자 하는 OR 가 1 에 가까울수록 sample 폭증. 작은 효과 검출이 가장 비싼 일.

2.8 코드 — OR + MH + Logistic

import numpy as np
import pandas as pd
import statsmodels.api as sm

np.random.seed(42)
n = 1000

# 가상 case-control: confounder Z (성별)
Z = np.random.binomial(1, 0.5, n)

# 진성 OR: stratum 무관 OR=2 (no effect modification)
true_log_OR = np.log(2.0)
log_odds_Y = -2 + true_log_OR * np.random.binomial(1, 0.3, n) + 1.0 * Z
Y = np.random.binomial(1, 1 / (1 + np.exp(-log_odds_Y)), n)

# Logistic 으로 X 재구성
X = np.random.binomial(1, 0.3, n)
df = pd.DataFrame({"Y": Y, "X": X, "Z": Z})

# Crude OR
crude = pd.crosstab(df["X"], df["Y"])
a, b = crude.iloc[1, 1], crude.iloc[1, 0]
c, d = crude.iloc[0, 1], crude.iloc[0, 0]
crude_OR = (a * d) / (b * c)
print(f"Crude OR: {crude_OR:.2f}")

# MH by Z
def mh_or(df, x, y, z):
    num, den = 0, 0
    for z_val in df[z].unique():
        sub = df[df[z] == z_val]
        a_s = ((sub[x] == 1) & (sub[y] == 1)).sum()
        b_s = ((sub[x] == 1) & (sub[y] == 0)).sum()
        c_s = ((sub[x] == 0) & (sub[y] == 1)).sum()
        d_s = ((sub[x] == 0) & (sub[y] == 0)).sum()
        n_s = a_s + b_s + c_s + d_s
        num += (a_s * d_s) / n_s
        den += (b_s * c_s) / n_s
    return num / den

print(f"MH OR (Z 보정): {mh_or(df, 'X', 'Y', 'Z'):.2f}")

# Logistic
X_design = sm.add_constant(df[["X", "Z"]])
model = sm.Logit(df["Y"], X_design).fit(disp=0)
print(f"Logistic OR (Z 보정): {np.exp(model.params['X']):.2f}")

해석: Crude OR 이 Z confounding 으로 편향. MH 와 logistic 이 비슷한 보정 OR 산출.

3 결론

3 가지 분석 도구 (crude OR, MH, logistic) 가 case-control 분석의 표준. 단일 confounder 라면 MH 와 logistic 거의 동일, 다중·연속 confounder 라면 logistic 우선. Effect modification 의심 시 Breslow-Day + interaction 모형.

다음 글(B25)에서는 cases 와 controls 선정의 통계적 함의를 본다.

4 관련 주제

Subscribe

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