Kaplan-Meier 生存分析 Kaplan-Meier Estimation and Log-rank Test (KM / log-rank)
估计时间-事件终点的生存曲线、中位时间和指定时点生存率,并用 log-rank 检验比较组间曲线。
统计原理
在第 个事件时点,事件发生前风险集中有 人,当时发生 个事件。KM 生存率是各事件时点条件生存概率的连乘:
事件会让阶梯曲线下降;删失不会让曲线在该时点下降,只会让这个人在后续事件时点不再进入风险集。中位生存期是 首次降到 0.5 或以下的时间;如果曲线始终高于 0.5,中位数就是“未估计(NE)”,不是 0,也不是最大随访时间。
log-rank 检验在每个事件时点比较各组“观察事件数”和“在相同风险集构成下的期望事件数”,再把差异累积成卡方统计量。它对整条曲线做总体比较,在风险比大致恒定时通常最有效,但本身不直接给出 HR。
播放 36 名确定性模拟受试者的观察过程:事件使 KM 曲线下降,删失只移出后续风险集;可拖动旋转、滚轮缩放。
Drug A 风险集
Placebo 风险集
最新观察
等待播放:尚无事件或删失。
已处理 / 36 名受试者
- —
- —
- —
Drug A
Placebo
●事件:曲线垂直下降
×删失:曲线保持水平
HR 改变 Drug A 的潜在事件速度;拖动滑杆会重建时间线并回到第 0 月。
交互场景尚未初始化。
什么时候用
终点是从起点到某事件发生的时间(如 OS、PFS、MACE 时间),且截至数据截止日仍有部分受试者未发生事件时,用 Kaplan-Meier(KM)方法估计生存函数;需要比较两组整条曲线时,通常同时给出 log-rank 检验。
SAP 里长这样:
Overall survival will be summarized by treatment group using the Kaplan-Meier method. The median survival time and its two-sided 95% confidence interval, together with survival probabilities at Months 6 and 12, will be presented. Treatment groups will be compared using a two-sided log-rank test.
看到 Kaplan-Meier / median survival / survival probability / log-rank,即可定位到本页。KM 负责“曲线和分位数怎么估”,log-rank 负责“组间曲线是否有系统差异”。
适用条件速查卡
| 项 | 条件 |
|---|---|
| 终点类型 | 时间-事件;AVAL 为从 SAP 规定起点到事件或删失日的分析时间 |
| 组数 | 1 组可做 KM 描述;2 组及以上可做 log-rank 比较 |
| 分析数据范围 | 先按目标 PARAMCD(示例为 OS)和 ANL01FL='Y' 限定;每名受试者对该参数恰好一条分析记录 |
| 事件/删失方向 | 本页 ADTTE 约定 CNSR=0 为事件、CNSR=1 为删失,因此 SAS 写 time aval*cnsr(1) |
| 主要前提 | 删失对未来事件风险是非信息性的;时间起点、事件和删失规则已由 SAP 预先定义 |
| 不满足时 | 有竞争事件 → 累积发生函数/Fine-Gray;明显非比例风险且要比较总体疗效 → RMST 或 SAP 预设的加权检验 |
核心 SAS 代码
ods graphics on;
ods output Quartiles=km_quartiles
ProductLimitEstimates=km_survival
HomTests=km_logrank;
proc lifetest data=adtte(
where=(paramcd='OS' and anl01fl='Y')
) plots=survival(atrisk cb=hw)
timelist=180 360 reduceout conftype=loglog;
time aval*cnsr(1); /* 括号中的 1 是删失值;0 才计为事件 */
strata trt01p / test=logrank; /* 此处 TRT01P 是要比较的曲线分组 */
run;
ods output close;
ods graphics off;
where=先把 ADTTE 限定到一个目标终点和主分析记录;若 OS/PFS 混在一起,KM 结果没有临床含义。time aval*cnsr(1)中括号列的是删失水平,不是事件水平。本页数据为0=事件,1=删失。timelist=180 360输出第 180/360 天生存率;正式程序应按 SAP 的月换算规则决定天数,不能默认“1 月=30 天”。strata trt01p在本页用于生成治疗组曲线和普通 log-rank 检验。SAP 若要求按随机分层因素做分层 log-rank,不能仅照抄这一行,应使用 SAP 指定的分层实现。
变量解释表
| 变量 | 含义 | 典型来源 |
|---|---|---|
| USUBJID | 受试者唯一标识 | ADTTE.USUBJID |
| TRT01P | 计划治疗组;决定 KM 曲线分组 | ADSL.TRT01P → ADTTE.TRT01P |
| STRATUM1 | IxRS 基线风险层;保留供 QC,本页普通 log-rank 不使用 | ADSL.STRATUM1 → ADTTE.STRATUM1 |
| PARAMCD | 时间-事件参数代码;本页仅分析 OS | ADTTE.PARAMCD |
| AVAL | 分析时间,单位必须与 SAP/shell 一致 | ADTTE.AVAL |
| CNSR | 删失标记;本页 0=事件,1=删失 | ADTTE.CNSR |
| ANL01FL | 主分析记录标记;本页仅取 Y | ADTTE.ANL01FL |
| EVNTDESC | 事件或删失原因的可读说明,用于 QC | ADTTE.EVNTDESC |
输出对照
下面是贴近 PROC LIFETEST 输出结构的示意数值,用于说明抄数位置;正式 TFL 必须使用经验证程序对正式 ADTTE 的实际输出。
Quartile Estimates
| TRT01P | Percent | Estimate | 95% Lower CL | 95% Upper CL |
|---|---|---|---|---|
| Drug A | 50 | 355 ① | 235 ② | NE ② |
| Placebo | 50 | 218 ① | 126 ② | 330 ② |
Product-Limit Survival Estimates(Day 180)
| TRT01P | Timelist | Survival | 95% Lower CL | 95% Upper CL |
|---|---|---|---|---|
| Drug A | 180 | 0.790 ③ | 0.491 ④ | 0.924 ④ |
| Placebo | 180 | 0.600 ③ | 0.319 ④ | 0.797 ④ |
Test of Equality over Strata
| Test | Chi-Square | Pr > Chi-Square |
|---|---|---|
| Log-Rank | 3.26 | 0.0710 ⑤ |
对应 shell(Table 14.2.x Overall Survival):
| Shell 行 | 填入 |
|---|---|
| Median OS, days | ① |
| 95% CI for median | (②, ②);上限未估计时按 shell 规则显示 NE |
| OS rate at Day 180, % | ③ × 100 |
| 95% CI for Day 180 rate, % | (④ × 100, ④ × 100) |
| Log-rank p-value | ⑤ |
示例数据与程序
- example.csv — 30 例原创模拟 OS 记录,采用 ADTTE 风格变量与
CNSR=0/1约定 - example.sas — 数据导入、范围限定、KM 曲线、中位数、时点生存率和 log-rank 检验完整程序
常见坑
常见坑
- CNSR 写反:若数据实际为 1=事件,却仍写
cnsr(1),事件会全部被当成删失。先查 ADTTE 规范与频数,再核对事件数。 - 混入多个参数或非主分析记录:必须同时限定目标
PARAMCD和ANL01FL=‘Y’,并确认每名受试者每个参数仅一条记录。 - 时间单位或起点不一致:AVAL 是天还是月、Day 1 是否加 1、死亡/失访/数据截止如何删失,都应来自 SAP 与 ADTTE 规范。
- 把删失刻度当成事件:KM 图上的小刻度表示删失,曲线下降才表示事件;风险集人数也要按同一显示时点核对。
- 把 NE 填成 0:中位数或置信限未达到时应按 shell 规则显示 NE/NR,不能用 0 或最后观察时间代替。
- 把 log-rank 当成 HR:log-rank 只给总体比较 p 值;要报告 HR 和协变量校正结果,应使用 Cox 模型。
相关方法
- Cox 比例风险回归 用半参数比例风险模型估计治疗组风险比及置信区间,并可按随机分层因素分层或校正协变量。