生存分析研究从明确定义的起点到事件发生的时间。它不仅用于死亡,也适用于复发、设备故障、客户流失等时间结局。
普通均值比较无法正确处理随访结束时尚未发生事件的对象;生存分析通过删失机制保留他们已经贡献的随访信息。
数据结构
最基本的生存数据包含:
| 变量 | 含义 |
|---|---|
time |
从起点到事件或删失的时间 |
status |
1 表示事件发生,0 表示删失 |
| 分组或协变量 | 治疗、性别、年龄等解释变量 |
起点、事件和时间单位必须在研究设计中明确。不同对象使用不同起点,会让时间不可比较。
删失
右删失表示在最后一次观察时尚未见到事件,例如研究结束、退出随访或失访。
Kaplan–Meier 等常用方法通常要求删失在给定分析信息后与事件过程相容。若高风险患者更容易失访,简单地把失访当作普通删失可能产生偏倚。
创建生存对象
survival::lung 中原始 status 使用 1 表示删失、2 表示死亡,需要先转换:
library(survival)
data(lung)
lung$status01 <- ifelse(lung$status == 2, 1, 0)
lung$sex <- factor(
lung$sex,
levels = c(1, 2),
labels = c("Male", "Female")
)
survival_outcome <- with(
lung,
Surv(time = time, event = status01)
)
在使用任何数据集前都要核查事件编码,不能假设 1 永远代表事件。
Kaplan–Meier 估计
km_fit <- survfit(
survival_outcome ~ sex,
data = lung
)
km_fit
summary(km_fit)
Kaplan–Meier 曲线在事件时间下降,删失不会造成下降,但会减少之后仍处于风险集的人数。
生存概率与中位生存时间
查看指定时间的生存概率:
summary(km_fit, times = c(180, 365))
中位生存时间是估计生存概率首次降到 0.5 的时间:
summary(km_fit)$table[, "median"]
如果随访期间曲线始终高于 0.5,中位生存时间尚未达到,不应强行外推一个数值。
组间比较
log-rank 检验比较各组在整个随访期间的事件过程:
survdiff(
Surv(time, status01) ~ sex,
data = lung
)
它检验的是整条生存曲线是否存在差异,不直接给出效应大小。若需要调整协变量或估计相对风险,通常使用 Cox 比例风险模型。
多组两两比较会产生多重检验问题:
library(survminer)
pairwise_survdiff(
Surv(time, status01) ~ factor(ph.ecog),
data = lung,
p.adjust.method = "BH"
)
累积风险
生存函数 与累积风险 描述同一事件过程的不同侧面。在常见关系下:
累积风险随时间增加,曲线上升越快表示风险累积越快。它不是某个瞬间发生事件的概率。
绘图所需信息
一张可解释的 Kaplan–Meier 图通常包括:
- 清晰的时间单位和结局定义;
- 各组生存曲线;
- 置信区间;
- 删失标记;
- 风险人数表;
- 组间比较方法;
- 必要时的中位生存时间。
library(survminer)
ggsurvplot(
km_fit,
data = lung,
conf.int = TRUE,
risk.table = TRUE,
pval = TRUE,
legend.title = "Sex"
)
本页关注这些元素的统计含义;具体成图、导出和视觉选择由 Tessera 的生存曲线配方负责。
下一步:Cox 模型
Cox 比例风险模型用于同时纳入多个协变量并估计 hazard ratio。使用前需检查比例风险假设、连续变量函数形式、事件数量和影响点。
Kaplan–Meier 与 log-rank 适合未调整的组间描述和比较;Cox 模型回答条件于协变量的相对风险问题,二者不能简单互相替代。