R ggplot2绘制带95%CI的合并Kaplan-Meier生存曲线方法咨询
Kaplan-Meier双队列曲线合并绘制方案
核心实现逻辑
- 针对NA值:KM曲线相邻终点事件之间生存概率、95%CI保持恒定,数据集中的NA对应无事件发生的时间点,采用末次观测值向前填充补全,无需删除行,从根源解决曲线断裂问题
- 针对KM形态:使用阶梯图图层替代普通折线图,严格匹配KM曲线“水平恒定、事件点垂直下降”的阶梯特性
- 针对同图映射:将宽格式数据转换为长格式,通过ggplot的颜色、填充美学映射统一绘制双队列,自动生成合并的规范图例
- 针对绘图标准化:统一坐标范围、配色、主题参数,输出符合学术规范的生存曲线
可复现代码
1. 依赖包加载
library(ggplot2) library(dplyr) library(zoo) library(tidyr) library(scales)
2. 数据预处理
# 统一列名,适配长宽表转换 km_data_renamed <- kmcurvetest_2 %>% rename( Cohort1_Survival = Cohort1, Cohort1_Lower = C1Lower95, Cohort1_Upper = C1Upper95, Cohort2_Survival = Cohort2, Cohort2_Lower = C2Lower95, Cohort2_Upper = C2Upper95 ) # 填充NA值:按时间升序排列后,向前结转最后一个非NA观测值 km_data_filled <- km_data_renamed %>% arrange(Time) %>% mutate(across(-Time, ~zoo::na.locf(.x, na.rm = FALSE))) # 宽表转长表,满足ggplot分组绘图要求 km_data_long <- km_data_filled %>% pivot_longer( cols = -Time, names_to = c("Cohort", "Metric"), names_sep = "_" ) %>% pivot_wider(names_from = Metric, values_from = value) %>% # 可根据需求修改队列显示名称,比如替换为英文"Cohort 1"、"Cohort 2" mutate(Cohort = recode(Cohort, "Cohort1" = "队列1", "Cohort2" = "队列2"))
3. 绘图代码
km_plot <- ggplot(km_data_long, aes(x = Time, group = Cohort)) + # 图层1:95%置信带(放在最底层) geom_ribbon( aes(ymin = Lower, ymax = Upper, fill = Cohort), alpha = 0.2, colour = NA ) + # 图层2:KM阶梯线,direction = "hv" 严格匹配KM曲线形态 geom_step( aes(y = Survival, color = Cohort), linewidth = 0.8, direction = "hv" ) + # 图层3:事件点标记(可根据需求删除) geom_point( aes(y = Survival, color = Cohort), size = 1 ) + # 标签配置 labs( title = "住院患者生存曲线", x = "时间(天)", y = "生存概率", color = "研究队列", fill = "研究队列" ) + # 坐标轴配置 scale_y_continuous( limits = c(0, 1), labels = percent_format(), expand = c(0.01, 0) ) + scale_x_continuous(expand = c(0, 0)) + # 配色配置(和原有单图蓝红配色保持一致) scale_color_manual(values = c("队列1" = "#1f77b4", "队列2" = "#d62728")) + scale_fill_manual(values = c("队列1" = "#1f77b4", "队列2" = "#d62728")) + # 标准化主题 theme_bw() + theme( plot.title = element_text(hjust = 0.5, size = 14, face = "bold"), axis.text = element_text(size = 11), axis.title = element_text(size = 12), legend.position = "bottom", legend.text = element_text(size = 11), panel.grid.minor = element_blank() ) # 输出图片 print(km_plot)
注意事项
- 禁止使用
geom_line绘制KM曲线:普通折线会在相邻时间点之间绘制斜线段,完全不符合KM曲线的阶梯恒定特性,必须使用geom_step并设置direction = "hv" - NA填充逻辑不可替换为插值/均值填充:KM曲线在无事件时间段生存概率不会发生变化,末次观测值结转是唯一符合统计学原理的填充方式
- 图例自动合并:由于
color和fill美学均映射到同一个Cohort变量,且配色保持一致,ggplot会自动将两个图例合并为单个规范图例,无需额外调整
内容的提问来源于stack exchange,提问作者DH617
相关产品推荐
相关产品推荐

