复现顶刊Kaplan-Meier curves !
本次使用s41591-023-02790-x中的代码、数据来复现Nature medcine中的Kaplan-Meier curves。
Kaplan-Meier曲线常用于生存分析(Survival analysis)评估疗效。例如,下图中,在一个肝内胆管癌免疫治疗队列研究中,使用了某种免疫治疗药物后,TNB-high组患者的OS明显长于TNB-other组患者,可初步得出TNB-high组患者更受益于该药物。
下面使用R制作Kaplan-Meier curves,
✅数据预处理
# 设置图形输出参数:宽度8英寸,高度6英寸,分辨率200 DPI
options(repr.plot.width = 8, repr.plot.height = 6, repr.plot.res = 200)
# 加载生存分析和可视化所需的R包
library(survival) # 用于生存分析,如Cox模型和生存曲线拟合
library(survminer) # 用于绘制专业的生存曲线(Kaplan-Meier曲线)
#----------------------------------------------------------------------------------
# Step 1: 加载数据
#----------------------------------------------------------------------------------
# (1) 读取191例PDAC患者(RJ队列1)的临床信息表
rj1.cohort <- read.xlsx("r_data/PDAC2_data_results/data/Extended Data Table 2.xlsx", startRow = 2)
# (2) 读取32个功能模块在癌组织(PDAC)和癌旁组织(TAC)中的ssGSEA评分矩阵,并进行转置(行为模块,列为样本)
module.ssgsea.pro.all <- read.xlsx("r_data/PDAC2_data_results/data/Extended Data Table 4.xlsx", sheet = 2, startRow = 2, rowNames = T)
module.ssgsea.pro.all <- t(module.ssgsea.pro.all) # 转置矩阵,使行名为模块名(如ME11),列名为样本ID
#----------------------------------------------------------------------------------
# Step 2: 基于ME11模块进行总生存期(OS)分析
#----------------------------------------------------------------------------------
# 准备绘图数据:将ME11模块的评分添加到临床数据中,并根据其中位数将患者分为"High"/"Low"两组
plot.cohort <- rj1.cohort %>%
mutate(
ME11_pro = as.numeric(module.ssgsea.pro.all["ME11", Proteomic_ID]), # 提取每个样本的ME11评分
ME11_pro_l = ifelse(ME11_pro >= median(ME11_pro), "High", "Low"), # 按中位数分组
ME11_pro_l = factor(ME11_pro_l, levels = c("Low", "High")), # 将分组设为因子,确定比较顺序
# 以下两行处理化疗状态因子,创建两种水平的因子用于可能的不同分析对比
Censoring_chemo_rev = Censoring_chemo,
Censoring_chemo = factor(Censoring_chemo, levels = c("Chem", "NoChem")),
Censoring_chemo_rev = factor(Censoring_chemo_rev, levels = c("NoChem", "Chem"))
)
head(plot.cohort)
✅ 计算p值、CI等统计指标
Hazard Ratio:HR,风险比; Confidence Interval:CI,置信区间; Cox P-value; Kaplan-Meier P-value;
# 执行Cox比例风险回归分析,检验ME11分组(High vs Low)与总生存期(OS)的关系
info <- summary(coxph(Surv(OS_month, OS_status) ~ ME11_pro_l, data = plot.cohort))
# 生成统计结果注释文本,包括风险比(HR)、置信区间(CI)和P值
anno.text <- ""
for (i in1:nrow(info$conf.int)) {
anno.text <- paste0(anno.text, "\n", paste0(rownames(info$conf.int)[i], " HR=", round(info$conf.int[i, 1], 3), " CI=", round(info$conf.int[i, 3], 3), "-", round(info$conf.int[i, 4], 3), " P=", signif(info$coefficients[i, 5], 4) ))
}
# 添加Log-rank检验(Kaplan-Meier法)的P值
anno.text <- paste0(anno.text, "nKaplan-Meier P=", signif(survdiff(Surv(OS_month, OS_status) ~ ME11_pro_l, data = plot.cohort)$pvalue, 4) )
anno.text <- str_replace_all(anno.text, "ME11_pro_l", "") # 清理文本中的变量名
anno.text
✅拟合Kaplan-Meier生存曲线
# 使用survfit函数拟合Kaplan-Meier生存曲线
fit <- survfit(Surv(OS_month, OS_status) ~ ME11_pro_l, data = plot.cohort)
fit
✅绘制Kaplan-Meier生存曲线
# 使用ggsurvplot可视化fit
p1 <- ggsurvplot(fit,
data = plot.cohort,
xlab = 'Time (Months)', # X轴标签
pval = TRUE, # 在图上显示Log-rank检验的P值
risk.table = TRUE, # 在曲线下方添加风险表,显示各时间点的风险患者数
risk.table.height = 0.28, # 风险表的高度占比
conf.int.alpha = 0.05, # 置信区间的透明度
conf.int = TRUE, # 绘制生存曲线的置信区间
palette = c("#00599F","#d80700"), # 定义颜色,蓝色代表"Low"组,红色代表"High"组
axes.offset = TRUE, # 坐标轴偏移
break.time.by = 12, # X轴刻度间隔为12个月
xlim = c(0, 48), # X轴范围限制在0到48个月
font.title = 12,
title= paste0("OS ME11_pro_l \n", anno.text)) # 图形标题,包含统计结果
p1 # 显示图形
✅完整Kaplan-Meier生存曲线代码
# 设置图形输出参数:宽度8英寸,高度6英寸,分辨率200 DPI
options(repr.plot.width = 8, repr.plot.height = 6, repr.plot.res = 200)
# 加载生存分析和可视化所需的R包
library(survival) # 用于生存分析,如Cox模型和生存曲线拟合
library(survminer) # 用于绘制专业的生存曲线(Kaplan-Meier曲线)
#----------------------------------------------------------------------------------
# Step 1: 加载数据
#----------------------------------------------------------------------------------
# (1) 读取191例PDAC患者(RJ队列1)的临床信息表
rj1.cohort <- read.xlsx("r_data/PDAC2_data_results/data/Extended Data Table 2.xlsx", startRow = 2)
# (2) 读取32个功能模块在癌组织(PDAC)和癌旁组织(TAC)中的ssGSEA评分矩阵,并进行转置(行为模块,列为样本)
module.ssgsea.pro.all <- read.xlsx("r_data/PDAC2_data_results/data/Extended Data Table 4.xlsx", sheet = 2, startRow = 2, rowNames = T)
module.ssgsea.pro.all <- t(module.ssgsea.pro.all) # 转置矩阵,使行名为模块名(如ME11),列名为样本ID
#----------------------------------------------------------------------------------
# Step 2: 基于ME11模块进行总生存期(OS)分析
#----------------------------------------------------------------------------------
# 准备绘图数据:将ME11模块的评分添加到临床数据中,并根据其中位数将患者分为"High"/"Low"两组
plot.cohort <- rj1.cohort %>%
mutate(
ME11_pro = as.numeric(module.ssgsea.pro.all["ME11", Proteomic_ID]), # 提取每个样本的ME11评分
ME11_pro_l = ifelse(ME11_pro >= median(ME11_pro), "High", "Low"), # 按中位数分组
ME11_pro_l = factor(ME11_pro_l, levels = c("Low", "High")), # 将分组设为因子,确定比较顺序
# 以下两行处理化疗状态因子,创建两种水平的因子用于可能的不同分析对比
Censoring_chemo_rev = Censoring_chemo,
Censoring_chemo = factor(Censoring_chemo, levels = c("Chem", "NoChem")),
Censoring_chemo_rev = factor(Censoring_chemo_rev, levels = c("NoChem", "Chem"))
)
# 执行Cox比例风险回归分析,检验ME11分组(High vs Low)与总生存期(OS)的关系
info <- summary(coxph(Surv(OS_month, OS_status) ~ ME11_pro_l, data = plot.cohort))
# 生成统计结果注释文本,包括风险比(HR)、置信区间(CI)和P值
anno.text <- ""
for (i in1:nrow(info$conf.int)) {
anno.text <- paste0(anno.text, "n", paste0(rownames(info$conf.int)[i], " HR=", round(info$conf.int[i, 1], 3), " CI=", round(info$conf.int[i, 3], 3), "-", round(info$conf.int[i, 4], 3), " P=", signif(info$coefficients[i, 5], 4) ))
}
# 添加Log-rank检验(Kaplan-Meier法)的P值
anno.text <- paste0(anno.text, "\nKaplan-Meier P=", signif(survdiff(Surv(OS_month, OS_status) ~ ME11_pro_l, data = plot.cohort)$pvalue, 4) )
anno.text <- str_replace_all(anno.text, "ME11_pro_l", "") # 清理文本中的变量名
# 使用survfit函数拟合Kaplan-Meier生存曲线
fit <- survfit(Surv(OS_month, OS_status) ~ ME11_pro_l, data = plot.cohort)
# 使用ggsurvplot绘制生存曲线图,并设置多种可视化参数
p1 <- ggsurvplot(fit,
data = plot.cohort,
xlab = 'Time (Months)', # X轴标签
pval = TRUE, # 在图上显示Log-rank检验的P值
risk.table = TRUE, # 在曲线下方添加风险表,显示各时间点的风险患者数
risk.table.height = 0.28, # 风险表的高度占比
conf.int.alpha = 0.05, # 置信区间的透明度
conf.int = TRUE, # 绘制生存曲线的置信区间
palette = c("#00599F","#d80700"), # 定义颜色,蓝色代表"Low"组,红色代表"High"组
axes.offset = TRUE, # 坐标轴偏移
break.time.by = 12, # X轴刻度间隔为12个月
xlim = c(0, 48), # X轴范围限制在0到48个月
font.title = 12,
title= paste0("OS ME11_pro_l n", anno.text)) # 图形标题,包含统计结果
p1 # 显示图形
本文结束!
(加入学习,收费,备注:299)