이 포스트는
effect_measures.qmd의 시간 일반화다. RR/OR 이 사건의 유무 (이항) 를 보는 반면, 시간-사건 분석은 “사건이 언제 일어나는가” 를 정량화한다. 일부 환자는 추적 종료까지 사건을 겪지 않아 (censoring) 단순 비율로 다룰 수 없다.
1 정의
각 개체에 대해 (1) 시간 \(T_i\) 와 (2) 관측 종료 시점에 사건이 일어났는지 여부 \(\delta_i \in \{0, 1\}\) 가 함께 관측되는 데이터.
- 사건 시간 \(T_i\): 처치/노출 시점부터 사건 발생까지의 시간
- 중도절단 (Censoring) \(\delta_i = 0\): 추적 종료까지 사건이 일어나지 않음 (right censoring)
- 위험 집단 (Risk Set): 시점 \(t\) 에 아직 사건을 겪지 않고 추적 중인 개체 집합
핵심 도전: 중도절단 데이터에서 평균 사건 시간을 단순 평균으로 추정하면 편향된다 — 사건을 겪지 않은 사람의 정보를 무시할 수 없다.
A/B test 의 retention·churn 분석은 이 프레임워크의 IT 버전 (Kohavi, Tang, Xu, 2020, Ch.4).
100 명의 환자를 5 년 추적, 30 명이 사망 (이 중 평균 사망 시간은 2 년), 70 명이 5 년까지 생존. “평균 생존 시간” 을 어떻게 추정할까?
- Naive 1: 사건 시간만 평균 → 30 명의 평균 = 2 년 → 70 명의 정보 무시. 명백한 과소 추정.
- Naive 2: 모든 사람의 관측 시간 평균 → (30 × 2 + 70 × 5) / 100 = 4.1 년 → 70 명을 5 년에 사망한 것처럼 취급 (실제로는 그 후에도 살아있을 가능성). 과대 추정.
- 올바른 답: KM 으로 생존곡선 \(S(t)\) 추정 → 5 년 초과 영역은 비식별 (admin censoring) 로 다루고, 그 시점까지의 생존확률을 보고. 단일 평균 대신 곡선이나 RMST (Restricted Mean Survival Time) 사용.
A/B test 비유: 추천 알고리즘 A vs B 의 retention 비교. 6 개월 추적, 일부 사용자는 마지막 날 가입 (실제로 6 개월 후 어떻게 될지 모름). 단순 churn rate (30 일 내 이탈 / 전체) 는 가입 시점이 다양하면 편향. KM 으로 시간-기반 retention 곡선을 그려야 정직.
2 빈도 지표 — Risk·Rate·Prevalence
같은 데이터라도 분모와 시간 단위에 따라 지표가 달라진다.
2.1 Risk vs Rate vs Odds (재방문)
| 지표 | 분자 | 분모 | 단위 | 시간 정보 |
|---|---|---|---|---|
| Risk | 사건 수 | 인구 (한 시점) | 비율 (0~1) | 없음 (cumulative) |
| Incidence Rate (IR) | 사건 수 | person-time | 1/시간 | 필수 |
| Odds | 사건 수 | 비사건 수 | 비율 (0~∞) | 없음 |
| Prevalence | 보유자 수 | 인구 (한 시점) | 비율 (0~1) | 단면 |
- 100 명을 1 년 추적, 10 명이 사건을 겪고 90 명이 1 년 내내 추적됨
- Risk = 10 / 100 = 0.10 (10% 위험)
- Person-time = 10 × 0.5 + 90 × 1 = 95 person-years (사건 직전 0.5 년 가정)
- IR = 10 / 95 = 0.105 events/person-year
- 추적 기간이 짧거나 모든 사람이 끝까지 추적되면 Risk ≈ IR × 시간
- 중도절단이 많거나 시간이 길면 차이 커짐 — IR 만 안정적
2.2 Incidence Rate (IR) — Person-Time 의 의미
\[ \text{IR} = \frac{\text{새 사건 수}}{\text{Person-time at risk}} \]
person-time = 각 개체의 추적 시간 합. 100 명을 평균 0.95 년 추적하면 95 person-years.
- 장점: 동적 인구 (입사·퇴사·사망이 있는 코호트) 에서도 안정적 추정 가능
- 단점: 사건 위험이 시간에 따라 일정 (constant hazard) 이라는 가정 — 위반 시 시간 구간별로 분리 (piecewise constant)
- 단위: events/person-year, /1000 person-years 등
10 person-years 를 만드는 방법은 여러 가지:
| 시나리오 | n | 평균 추적 | 합 | IR (사건 1 건 시) |
|---|---|---|---|---|
| 1 명을 10 년 추적 | 1 | 10 | 10 PY | 0.10 / PY |
| 5 명을 2 년 추적 | 5 | 2 | 10 PY | 0.10 / PY |
| 10 명을 1 년 추적 | 10 | 1 | 10 PY | 0.10 / PY |
| 100 명을 0.1 년 추적 | 100 | 0.1 | 10 PY | 0.10 / PY |
constant hazard 가정 하에 시간을 어떻게 쪼개도 IR 동일. 이게 person-year 의 핵심 가치 — 동적 코호트 (사람이 들어오고 나가는) 에서도 통계적 비교 가능.
경고: constant hazard 가 깨지는 경우:
- Survivor bias: 5 년까지 살아남은 사람은 일반인보다 건강 → 위험률이 시간에 따라 감소
- Aging effect: 고령자가 추적될수록 위험률 증가
- 노출 잠복기: 약물 부작용은 노출 후 1~2 년 사이에 집중
이런 경우 단일 IR 대신 시간 구간별 IR (piecewise rate) 또는 hazard function \(h(t)\) 사용.
A/B test 사례: 신기능의 6 개월 retention 분석에서 첫 7 일은 호기심 (novelty) 으로 retention 률이 높고, 30 일 이후 안정. 단일 IR 은 평균이지만, \(h(t)\) 곡선을 그려야 진짜 패턴 보임.
(Woodward, 2014, Ch.5)
2.3 Cumulative Incidence vs Survival Function
\[ \text{Cumulative Incidence}(t) = P(T \le t) = 1 - S(t) \]
여기서 \(S(t) = P(T > t)\) 는 생존함수.
- 시점 \(t\) 까지 사건을 겪지 않은 비율
- KM 곡선이 추정하는 양
2.4 Prevalence vs Incidence
| 항목 | 정의 | 시간 |
|---|---|---|
| Incidence (발생률) | 새 사건 발생 | 단위 시간당 |
| Prevalence (유병률) | 현재 보유자 비율 | 한 시점 |
Prevalence ≈ Incidence × 평균 사건 지속시간 (steady-state). HIV 환자 수가 늘어도 신규 발생이 줄면 prevalence 만 증가하고 incidence 는 감소.
3 시간 비교 지표 — RR 의 시간 일반화
3.1 Incidence Rate Ratio (IRR) / Difference (IRD)
\[ \text{IRR} = \frac{\text{IR}_E}{\text{IR}_{\bar E}}, \quad \text{IRD} = \text{IR}_E - \text{IR}_{\bar E} \]
- IRR 은 RR 의 시간 일반화 — Poisson 회귀의 자연스러운 추정량
- IRD 는 RD 의 시간 일반화 — “추가 사건/person-year”
3.2 Hazard Function — 순간 위험률
\[ h(t) = \lim_{\Delta t \to 0} \frac{P(t \le T < t + \Delta t \mid T \ge t)}{\Delta t} \]
- \(h(t)\) 는 시점 \(t\) 까지 사건을 겪지 않은 사람이 다음 순간에 사건을 겪을 순간 비율
- \(S(t) = \exp\left(-\int_0^t h(u)\,du\right)\) 로 생존함수와 연결
- IR 은 \(h(t)\) 의 평균에 해당 (constant hazard 가정 시 \(h \equiv \text{IR}\))
\(h(t)\) 의 분모가 \(T \ge t\) — 즉 시점 \(t\) 까지 사건을 겪지 않은 사람만 분모에 포함. 시간이 지나면서 이미 사건을 겪은 사람은 빠지므로 hazard 는 conditional rate 다.
비유 — 비행기 여정:
- 1 시간 비행 중 추락할 확률: 누적 위험 (cumulative incidence)
- 50 분 비행했는데 안 떨어졌을 때 다음 1 분에 떨어질 확률: hazard \(h(50)\)
비행이 길어질수록 이미 안전한 항로를 통과 → 남은 시간의 추락 확률은 일반적으로 일정 또는 감소 (hazard 가 시간에 따라 변동).
\(S(t)\) 와 \(h(t)\) 의 관계 — 적분의 의미:
\[ S(t) = \exp\left(-\int_0^t h(u)\, du\right) \]
매 순간의 hazard 를 누적해서 지수의 음의 부호로 적용. 직관: 매 순간 작은 비율 \(h(u) \cdot du\) 만큼 사람이 사라지는 연속적 감소 모델 (radioactive decay 와 동일 수학).
constant hazard \(h \equiv \lambda\) 면 \(S(t) = e^{-\lambda t}\) — exponential 분포. 이게 IR 의 base.
hazard 모양 (shape) 별 직관:
- 상승 (increasing): aging — 고령일수록 사망 위험 증가 (Gompertz, Weibull k>1)
- 하강 (decreasing): burn-in — 새 부품·신생아 사망률 (Weibull k<1)
- U-자형 (bathtub): 인간 수명 — 영아·노인이 위험, 청장년 안전
- 상수 (constant): 무작위 사건 — 방사성 붕괴, 일정한 사건 빈도 (exponential)
3.3 Hazard Ratio (HR) — 가장 중요한 시간 비교 지표
\[ \text{HR} = \frac{h_E(t)}{h_{\bar E}(t)} \]
- 노출군의 순간 사건 위험이 비노출군 대비 몇 배인가
- 비례 위험 (Proportional Hazards) 가정 하에 시간에 따라 일정
- Cox PH 모델의 회귀 계수가 직접 log HR
HR = 1.5 는 “처치군이 1.5 배 빨리 사건 발생” 도 아니고 “위험이 1.5 배” 도 아니다.
- 정확히는: 사건이 일어나기 직전 순간에 한정하여, 처치군의 사건 발생 강도가 비노출군의 1.5 배
- 누적 사건률 (1 - S(t)) 의 비율은 시간에 따라 다름
- 평균 생존 시간의 비율도 아님
HR 은 직관적으로 RR 처럼 보이지만 수학적으로 다르다 (non-collapsible).
(Hernan & Robins, 2020, Ch.17 — Causal Survival Analysis)
4 표준화 지표 — 인구 비교의 lens
연령·성별 분포가 다른 인구를 비교할 때 raw rate 를 그대로 비교하면 편향. 표준화 (standardization) 가 필수.
4.1 Direct Standardization
\[ \text{표준화된 비율} = \sum_i w_i \cdot \text{IR}_i \]
- \(w_i\): 표준 인구의 stratum 비율
- \(\text{IR}_i\): 비교 인구의 stratum 별 IR
- 결과: 표준 인구에 비교 인구의 stratum 별 IR 을 적용했을 때의 가상 비율
4.2 Indirect Standardization — SMR / SIR
\[ \text{SMR} = \frac{\text{관찰된 사망 수}}{\text{기대 사망 수}}, \quad \text{Expected} = \sum_i n_i \cdot \text{IR}_i^{\text{ref}} \]
- SMR (Standardized Mortality Ratio): 사망 사건
- SIR (Standardized Incidence Ratio): 발생 사건
- \(\text{IR}_i^{\text{ref}}\): 기준 인구의 stratum 별 IR
- \(n_i\): 비교 인구의 stratum 별 사이즈
해석: - SMR = 1.5 → 비교 인구의 사망이 기준 인구 대비 50% 더 많음 - 직업·지역 역학에서 핵심 (예: 광부 SMR vs 일반 인구)
광부 인구의 사망률이 일반 인구보다 높은가? 단순 비교는 위험: 광부는 평균 연령이 높아서 그냥 늙어서 더 죽을 수도 있다 (교란).
SMR 의 사고 실험:
- 광부 인구의 연령대별 인원: 30~44 세 1000 명, 45~59 세 800 명, 60~74 세 400 명
- 일반 인구 (기준) 의 연령대별 사망률: 0.5/1000, 5/1000, 50/1000 (per year)
- 만약 광부가 일반 인구처럼 살았다면 기대 사망 수:
- 0.5/1000 × 1000 + 5/1000 × 800 + 50/1000 × 400 = 0.5 + 4 + 20 = 24.5 명
- 실제 광부 사망: 85 명 관측
- SMR = 85 / 24.5 ≈ 3.47 — 광부가 일반 인구보다 3.47 배 사망률
핵심 트릭: “기준 인구의 사망률을 광부 인구에 적용했을 때 기대되는 사망 수” 와 “실제 광부 사망 수” 비교. 연령 분포의 차이가 자동으로 보정됨 — 이게 “표준화” 의 의미.
Direct vs Indirect:
- Direct = 비교 인구의 사망률을 기준 인구 분포에 적용 → 가상의 “표준화된 사망률” 도출. 비교 인구가 작거나 stratum 별 데이터 부족 시 불안정.
- Indirect (SMR) = 기준 인구의 사망률을 비교 인구 분포에 적용 → 비교 인구가 작아도 안정적. 드물거나 작은 직업군에 특히 유용.
A/B test 비유: 신기능 retention 비교 시, 처치군과 대조군의 사용자 segment (신규/heavy/lapsed) 분포가 다르면 단순 비교 편향. SMR 처럼 “대조군의 segment 별 retention 률을 처치군 segment 분포에 적용한 기대값” 과 처치군 실제 retention 비교. CUPED 의 변형.
(Woodward, 2014, Ch.4)
4.3 Mantel-Haenszel — 층화 결합
여러 stratum 의 효과를 하나로 결합:
\[ \text{OR}_{MH} = \frac{\sum_i a_i d_i / n_i}{\sum_i b_i c_i / n_i}, \quad \text{IRR}_{MH} = \frac{\sum_i a_i (T_i^{\bar E}) / T_i}{\sum_i c_i (T_i^E) / T_i} \]
- 교란 통제의 고전적 분석 단계 방법
- 회귀의 base 가 되는 직관적 추정량
5 비모수·반모수 추정
5.1 Kaplan-Meier (KM) — 비모수 생존함수
\[ \hat S(t) = \prod_{t_j \le t} \left(1 - \frac{d_j}{n_j}\right) \]
- \(d_j\): 시점 \(t_j\) 의 사건 수
- \(n_j\): 시점 \(t_j\) 의 위험 집단 크기
- 분포 가정 없음 — 데이터에 충실
- 그룹별 KM 곡선 → 시각적 비교
KM 의 \(\prod\) 기호는 무서워 보이지만 직관은 단순:
시작: 100 명 모두 생존 (S(0) = 1.0)
↓
시점 t=1 에 5 명 사망:
살아남는 비율 = (100-5) / 100 = 0.95
S(1) = 1.0 × 0.95 = 0.95
↓
시점 t=2 에 censored (탈락) 10 명 (사건 아님, 분모만 줄어듦):
살아남는 비율 그대로 = 1 (사건 없음)
S(2) = 0.95 × 1 = 0.95
↓
시점 t=3 에 8 명 사망 (위험 집단 = 100-5-10 = 85):
살아남는 비율 = (85-8) / 85 = 0.906
S(3) = 0.95 × 0.906 = 0.860
각 사건 시점마다 “지금 위험에 있는 사람들 중 살아남는 비율” 을 곱한다. censored 는 분모에서 빠지지만 사건은 아님 — KM 의 핵심 장점.
왜 곱셈인가: \(S(t) = P(T > t)\) 는 “시점 \(t\) 까지 사건 없음” 이고, 이는 “각 사건 시점에서 사건 안 겪음” 의 연속이라 \(P(t_1 살아남음) \times P(t_2 살아남음 | t_1 살아남음) \times ...\) 로 분해.
시각화: KM 곡선은 사건 시점마다 한 칸씩 떨어지는 계단 함수. 일정한 곡선이 아니라 — 사건이 데이터에 있는 시점에만 떨어진다.
A/B test 비유: 사용자 1000 명 가입, 매주 일부가 churn. 8 주차에 누적 retention rate 를 보려면 KM 으로 계산 — 단순 (8 주 안 churn / 전체) 은 신규 가입자 (아직 8 주 안 됨) 를 잘못 다룬다.
5.2 Log-rank Test — 그룹 간 생존 차이 검정
\[ \chi^2 = \frac{(O_1 - E_1)^2}{V_1} \]
- 두 KM 곡선이 동일한가의 비모수 검정
- \(H_0\): 두 그룹의 생존함수 동일
- 비례 위험 가정 하에 가장 강력 (Mantel-Cox 통계량)
- Stratified log-rank: 교란 보정
5.3 Cox Proportional Hazards (PH) Model
\[ h(t \mid X) = h_0(t) \exp(\beta^T X) \]
- \(h_0(t)\): 기준 hazard (비모수)
- \(\beta\): 회귀 계수 — \(\exp(\beta_j)\) 가 공변량 \(X_j\) 한 단위 증가의 HR
- 부분 가능도 (partial likelihood) 로 \(\beta\) 추정 — 기준 hazard 함수 형태 가정 없음
선형 회귀 \(Y = \alpha + \beta X\) 는 절편 \(\alpha\) 와 기울기 \(\beta\) 를 모두 추정. Cox 는 기준 hazard \(h_0(t)\) 의 함수 형태를 전혀 가정하지 않고 \(\beta\) 만 추정한다. 어떻게?
부분 가능도 (partial likelihood) — 각 사건 시점 \(t_j\) 에서 “사건을 겪은 그 사람” 이 위험 집단 중에서 선택될 상대 확률만 사용:
\[ L_p(\beta) = \prod_{j: \text{사건}} \frac{\exp(\beta^T X_{(j)})}{\sum_{k \in R_j} \exp(\beta^T X_k)} \]
\(h_0(t)\) 는 분자·분모에 모두 들어가서 상쇄. 결과: 데이터의 시간 분포 모양을 모르고도 회귀 계수 추정 가능 — semi-parametric 의 본질.
비교: Weibull AFT 는 hazard 형태 (Weibull) 를 가정하고 추정 → 가정이 맞으면 더 효율적, 틀리면 편향. Cox 는 가정이 적어 robust.
\(\exp(\beta_j)\) = HR: 공변량 \(X_j\) 가 1 단위 증가하면 hazard 가 \(\exp(\beta_j)\) 배. 처치 = 1 vs 0 의 dummy 변수면 \(\exp(\beta_{\text{treat}})\) 가 처치-대조 HR.
왜 PH 인가: 모델이 \(h(t) = h_0(t) \cdot \exp(\beta^T X)\) 형태이므로 두 사람의 hazard 비 \(\frac{h(t \mid X_1)}{h(t \mid X_2)} = \exp(\beta^T (X_1 - X_2))\) 가 시간 \(t\) 에 무관 → “비례 위험”. 이 가정이 깨지면 다음 박스 참조.
비례 위험 가정이 깨지면 (HR 이 시간에 따라 변하면) Cox 결과는 시간 평균 HR 의 일종이 되어 해석이 모호해진다.
- 진단: Schoenfeld residuals plot, log(-log(S(t))) plot, 시간 의존 공변량 추가 후 검정
- 위반 시:
- 시간 의존 공변량 (time-varying coefficient) 으로 확장
- Stratified Cox (기준 hazard 를 stratum 별로 분리)
- AFT (Accelerated Failure Time) 모델 사용
- Restricted Mean Survival Time (RMST) 비교
(Hosmer, 2008; Kleinbaum, 2012)
5.4 Nelson-Aalen — 누적 hazard 추정
\[ \hat\Lambda(t) = \sum_{t_j \le t} \frac{d_j}{n_j} \]
- KM 의 hazard 버전
- \(\hat S(t) = \exp(-\hat\Lambda(t))\) 와 KM 이 거의 일치
5.5 AFT (Accelerated Failure Time) Model
\[ \log T = \beta^T X + \sigma \epsilon \]
- 공변량이 사건 시간을 직접 가속·감속
- Weibull, log-normal, log-logistic 분포 가정
- 해석: \(\exp(\beta_j)\) = 시간의 가속 인자 (HR 이 아님)
- PH 가정이 깨질 때 대안
6 Causal Survival Analysis
관찰 데이터에서 처치의 인과 효과를 추정하려면 교란 보정이 필요. 시간-사건 데이터에서는 추가 도전이 있다.
6.1 Time-Varying Confounding
처치가 시간에 따라 변하고 (time-varying treatment), 교란 변수도 시간에 따라 변하며, 과거 처치가 미래 교란에 영향을 줄 때 (treatment-confounder feedback) — 단순 회귀는 편향된다.
해결: g-methods (g-formula, IPW, g-estimation) — Hernan Ch.19~21.
6.2 IPW for Survival
각 개체에 안정화 IP weight \(sw_i(t)\) 를 부여한 weighted KM / Cox 로 처치 효과 추정.
\[ sw_i(t) = \prod_{k \le t} \frac{f(A_k \mid \bar A_{k-1})}{f(A_k \mid \bar A_{k-1}, \bar L_k)} \]
- 처치-교란 피드백 보정
- 비례 위험 가정 없이 한계 hazard ratio (marginal HR) 추정 가능
6.3 G-formula for Survival
\[ E[Y^a(t)] = \sum_l P(Y(t) = 1 \mid A = a, L = l) \cdot P(L = l) \]
- 결과 모델로 직접 표준화
- IPW 와 이중 강건성 (doubly robust) 결합 가능 (TMLE)
6.4 Causal HR vs 관측 HR
위에서 본 PH 가정 위반은 인과 추론 관점에서도 문제다. 처치가 random hazard 변동을 야기하면 marginal HR (인과적) 과 conditional HR (관측) 이 다르다 (non-collapsibility).
(Hernan & Robins, 2020, Ch.17)
7 메타분석 (시간 lens)
여러 연구의 HR 또는 IRR 을 결합하는 메타분석. 일반 효과 메타분석과 같지만 시간 데이터 특수성이 있다.
7.1 Pooled Effect Estimation
각 연구의 log HR 의 가중 평균:
\[ \widehat{\log \text{HR}}_{pooled} = \frac{\sum_i w_i \widehat{\log \text{HR}}_i}{\sum_i w_i} \]
- Fixed-effect: \(w_i = 1 / \text{Var}_i\)
- Random-effect (DerSimonian-Laird): \(w_i = 1 / (\text{Var}_i + \tau^2)\)
7.2 이질성 (Heterogeneity)
| 지표 | 정의 | 해석 |
|---|---|---|
| Q statistic Cochran’s Q | \(\sum w_i (\widehat{\log\text{HR}}_i - \widehat{\log\text{HR}}_{pooled})^2\) | 이질성 검정 (\(\chi^2\)) |
| I² Higgins | \(\max(0, (Q - df) / Q) \times 100\%\) | 이질성 분산 비율 (0~100%) |
| τ² Tau-squared | DerSimonian-Laird 추정량 | 연구 간 분산 (random-effects) |
해석 (Higgins, 2003): I² < 25% (낮음), 25~75% (중간), >75% (높음).
I² 는 “관찰된 효과 변동 중 진짜 연구 간 차이로 설명되는 비율” 이다.
- I² = 0%: 연구들이 모두 같은 효과를 추정 (변동은 표본 변동만). Fixed-effect 모델 적절.
- I² = 50%: 변동의 절반이 연구 간 진짜 차이 (연구 모집단·프로토콜·시점이 달라서). Random-effects 사용 권장.
- I² = 80%: 연구들이 사실상 다른 모집단을 보고 있음. Pooled effect 의 의미 의심 — sub-group 분석이나 meta-regression 필요.
비유 — 소문 합치기:
10 명의 친구에게 “오늘 점심 어디서 먹을까?” 물어보고 답을 합친다.
- 모두 “강남역” 이라 답하면 (I² ≈ 0%) “강남역” 이 결론. 한 사람의 답으로도 충분.
- 5 명 강남, 5 명 홍대 (I² ≈ 80%) → 단순 평균 (“강남 50%, 홍대 50%”) 은 무의미. 왜 의견이 갈리는가 (지역? 음식 선호?) 가 진짜 질문.
메타분석 보고 의무 (PRISMA 가이드라인):
- Pooled effect + 95% CI
- I² + τ² (이질성)
- Forest plot (개별 연구 + pooled)
- Funnel plot + Egger test (출판편향)
- Sub-group analysis (이질성 클 때)
I² 만 보고하지 않고 τ² 도 보고하는 이유: I² 는 분산 비율이라 표본 크기에 의존. 작은 메타분석에서 I² = 50% 라도 절대 분산 τ² 는 작을 수 있고, 큰 메타분석에서 I² = 25% 라도 τ² 는 클 수 있음. 두 지표가 보완.
7.3 출판편향 — Funnel Plot, Egger Test
- Funnel plot: 효과 크기 (x) vs 정밀도 (y) 산점도. 비대칭이면 출판편향 의심.
- Egger test: funnel 의 비대칭을 회귀로 검정.
8 응용 분야
| 분야 | 핵심 지표 | 사례 |
|---|---|---|
| 임상 추적 | KM, log-rank, Cox HR | 항암제 phase III 생존 비교 |
| 직업 역학 | SMR, SIR | 광부 폐암 위험 |
| A/B test retention | KM, HR | 신규 기능 도입 후 churn |
| 약물 안전성 | IR, IRR | post-marketing surveillance |
| 시스템 신뢰성 | Weibull AFT | 부품 수명 추정 |
| 정책 평가 | Difference-in-Differences with time | 정책 도입 전후 변화 |
9 예시 — 임상 추적 데이터
| n | 사건 수 | Person-years | IR | KM 5y survival | |
|---|---|---|---|---|---|
| 처치군 (T) | 200 | 30 | 850 | 0.0353 | 0.85 |
| 대조군 (C) | 200 | 50 | 700 | 0.0714 | 0.75 |
- IR_T = 30 / 850 = 35.3 / 1000 person-years
- IR_C = 50 / 700 = 71.4 / 1000 person-years
- IRR = 35.3 / 71.4 = 0.494 — 처치군 발생률이 50%
- IRD = -36.1 per 1000 person-years (처치군 36 명 적게 발생)
- HR (Cox 추정) ≈ 0.50, 95% CI [0.32, 0.78], p = 0.002
- 5 년 RMST 차이: 약 0.30 년 (처치군이 평균 0.30 년 더 생존)
해석: HR = 0.5 는 처치군 순간 위험이 절반. RMST 는 시간 척도 (months/years) 의 절대 차이로 환자에게 직관적.
10 코드
import numpy as np
import pandas as pd
from lifelines import KaplanMeierFitter, CoxPHFitter, NelsonAalenFitter
from lifelines.statistics import logrank_test
from lifelines.utils import restricted_mean_survival_time
# 데이터 시뮬레이션 (Weibull + censoring)
np.random.seed(42)
n_per_arm = 200
T_treat = np.random.weibull(1.5, n_per_arm) * 8 # 처치군: 평균 더 김
T_ctrl = np.random.weibull(1.5, n_per_arm) * 5
C = 5.0 # 추적 종료 시점
df = pd.DataFrame({
"time": np.concatenate([np.minimum(T_treat, C), np.minimum(T_ctrl, C)]),
"event": np.concatenate([(T_treat <= C).astype(int), (T_ctrl <= C).astype(int)]),
"treat": [1] * n_per_arm + [0] * n_per_arm
})
# 1. Incidence Rate
for arm in [0, 1]:
sub = df[df.treat == arm]
IR = sub.event.sum() / sub.time.sum() * 1000
print(f"Arm {arm}: events={sub.event.sum()}, PY={sub.time.sum():.1f}, IR={IR:.1f}/1000PY")
# 2. Kaplan-Meier
kmf = KaplanMeierFitter()
fig, ax = None, None # in real notebook: ax = plt.subplot()
for arm, name in [(1, "Treatment"), (0, "Control")]:
sub = df[df.treat == arm]
kmf.fit(sub.time, sub.event, label=name)
print(f"{name} 5y survival: {kmf.survival_function_at_times(5).iloc[0]:.3f}")
# 3. Log-rank test
result = logrank_test(
df[df.treat == 1].time, df[df.treat == 0].time,
df[df.treat == 1].event, df[df.treat == 0].event
)
print(f"Log-rank: stat={result.test_statistic:.2f}, p={result.p_value:.4f}")
# 4. Cox PH (HR 추정)
cox = CoxPHFitter()
cox.fit(df, duration_col="time", event_col="event", formula="treat")
HR = np.exp(cox.params_["treat"])
CI = np.exp(cox.confidence_intervals_.loc["treat"])
print(f"HR = {HR:.3f}, 95% CI [{CI[0]:.3f}, {CI[1]:.3f}]")
# 5. PH 가정 검정 (Schoenfeld residuals)
cox.check_assumptions(df, p_value_threshold=0.05, show_plots=False)
# 6. RMST (Restricted Mean Survival Time)
rmst_T = restricted_mean_survival_time(KaplanMeierFitter().fit(
df[df.treat==1].time, df[df.treat==1].event
), t=5.0)
rmst_C = restricted_mean_survival_time(KaplanMeierFitter().fit(
df[df.treat==0].time, df[df.treat==0].event
), t=5.0)
print(f"5y RMST 차이: {rmst_T - rmst_C:.3f} years")# SMR / SIR 계산 예시
import numpy as np
# 비교 인구 (광부): 연령대별 사이즈와 관찰 사망 수
age_groups = ["30-44", "45-59", "60-74"]
n_miners = np.array([1000, 800, 400])
obs_deaths = np.array([5, 20, 60])
# 기준 인구 (전체 일반 인구) 의 연령대별 사망률 (per 1000)
ref_rate = np.array([0.5 / 1000, 5.0 / 1000, 50.0 / 1000])
expected = (n_miners * ref_rate).sum()
observed = obs_deaths.sum()
SMR = observed / expected
SE_logSMR = np.sqrt(1 / observed)
CI_SMR = np.exp([np.log(SMR) - 1.96 * SE_logSMR, np.log(SMR) + 1.96 * SE_logSMR])
print(f"SMR = {SMR:.2f}, 95% CI [{CI_SMR[0]:.2f}, {CI_SMR[1]:.2f}]")
# SMR > 1 + CI 가 1 미포함 → 광부 사망률이 일반 대비 유의 증가11 관련 주제
선행 지식
- Effect Measures — RR/RD/NNT (시간 무시 lens)
- Relative Risk & Odds Ratio — base
- Study Design Overview
후속 주제 (Epidemiology 시리즈)
- Diagnostic & Screening Measures — Sn/Sp/LR (분류 lens)
Causal Inference 시리즈
- Causal Effect Definition — ATE/ATT
- Confounding
- Causal Survival Analysis (예정) — Hernan Ch.17
A/B Test 연결
- Sample Size & MDE
- Multi-arm Bandit — 시간 의존 의사결정
다른 카테고리 연결
- Statistics — Survival 시리즈 (예정) — Cox·AFT 정통
- LDA — Longitudinal Data Analysis — 시간 측정 데이터의 GLMM