You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R语言中如何将两个不同模型的Group 0生存曲线绘于同一图

合并两个模型Group 0生存曲线的解决方案

问题背景

我使用两个不同的二分类模型,二者测试样本数量不同且存在重叠。以预测得分的中位数为阈值,将每个模型的样本划分为Group 0和Group 1。目前能分别绘制两个模型Group 0的生存曲线,但无法合并到同一张图中展示。

现有代码

# `survivalCurve`是自定义函数,可绘制Group 0和Group 1的生存曲线,同时返回所用数据框
tme = survivalCurve(mymodel = model1, model_num = 8, use.TME = TRUE)
nontme = survivalCurve(mymodel = model2, model_num = 29, use.TME = FALSE)

# 提取两个模型的Group 0
tme_0 = tme %>% dplyr::filter(group == 0)
nontme_0 = nontme %>% dplyr::filter(group == 0)

# 尝试合并样本但仅能单独绘制曲线
tme_0$rowname = rownames(tme_0)
nontme_0$rowname = rownames(nontme_0)
zeros = merge(tme_0, nontme_0, by = "rowname", all = TRUE) 

zeros_x = zeros[!is.na(zeros$survival_time.x) & !is.na(zeros$survival_status.x), ]
zeros_y = zeros[!is.na(zeros$survival_time.y) & !is.na(zeros$survival_status.y), ]

# 创建生存对象
survival_object_x = Surv(time = zeros_x$survival_time.x, event = zeros_x$survival_status.x)
survival_object_y = Surv(time = zeros_y$survival_time.y, event = zeros_y$survival_status.y)

# 拟合生存曲线
fit_x = survfit(survival_object_x ~ 1)
fit_y = survfit(survival_object_y ~ 1)

# 分别绘制曲线
ggsurv_x = ggsurvplot(fit_x, data = zeros_x, risk.table = TRUE, pval = TRUE, conf.int = TRUE, legend.title = "Group X", legend.labs = c("Group X"), palette = c("blue"))
ggsurv_y = ggsurvplot(fit_y, data = zeros_y, risk.table = TRUE, pval = TRUE, conf.int = TRUE, legend.title = "Group Y", legend.labs = c("Group Y"), palette = c("red"))

数据结构示例

> dput(tme[1:20,])
structure(list(survival_time = c(9, 7, 8, 32, 27, 21, 5, 7, 25, 
15, 14, 30, 28, 6, 25, 27, 37, 63, 63, 22), survival_status = c(1, 
1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1), prediction_scores = c(0.452489739997856, 
0.440583099511596, 0.509308651793677, 0.457296723067907, 0.455967522911745, 
0.456091537587146, 0.52058697349597, 0.508446710238974, 0.468852537302421, 
0.401894923842953, 0.459980058832451, 0.488860355868262, 0.457574356551677, 
0.49155383636979, 0.470455235473811, 0.43061685052414, 0.428729855269241, 
0.442110813635852, 0.413582392521575, 0.407929513543207), group = structure(c(1L, 
1L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 
1L, 1L, 1L), levels = c("0", "1"), class = "factor")), row.names = c("Nivolumab_2017_p002_ar_8815", 
"Nivolumab_2017_p005_ar_8883", "Nivolumab_2017_p010_ar_8887", 
"Nivolumab_2017_p031_ar_8913", "Nivolumab_2017_p034_ar_8929", 
"Nivolumab_2017_p037_ar_8900", "Nivolumab_2017_p039_ar_8819", 
"Nivolumab_2017_p046_ar_8904", "Nivolumab_2017_p072_ar_8861", 
"Nivolumab_2017_p077_ar_8846", "Nivolumab_2017_p082_ar_8822", 
"Nivolumab_2017_p085_ar_8829", "Nivolumab_2017_p089_ar_8831", 
"Nivolumab_2017_p090_ar_8866", "Nivolumab_2017_p098_ar_8853", 
"Nivolumab_2017_p101_ar_8834", "EA595720", "EA632149", "EA632174", 
"EA639099"), class = "data.frame")

> dput(nontme[1:20,])
structure(list(survival_time = c(5, 31, 24, 36, 16, 15, 3, 5, 
30, 11, 27, 63, 17, 59, 42, 55, 14, 53, 16, 2), survival_status = c(0, 
0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1), prediction_scores = c(0.399196720335709, 
0.399196712585732, 0.399196718778835, 0.399196729515291, 0.399196719003673, 
0.39919672164811, 0.399196722134395, 0.399196714987811, 0.399196722354385, 
0.399196713792278, 0.39919672386451, 0.395944775789647, 0.395944769442692, 
0.395944782920291, 0.395944768860647, 0.395944773326361, 0.395944782577356, 
0.395944769654135, 0.39594477072273, 0.395944782418024), rank = c(144, 
112, 139, 182, 141, 150, 151, 125, 154, 117, 159, 52, 35, 77, 
32, 46, 75, 38, 40, 74), group = structure(c(1L, 1L, 1L, 2L, 
1L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
), levels = c("0", "1"), class = "factor")), row.names = c("Nivolumab_2017_p024_ar_8906", 
"Nivolumab_2017_p026_ar_8920", "Nivolumab_2017_p028_ar_8922", 
"Nivolumab_2017_p036_ar_8898", "Nivolumab_2017_p062_ar_8856", 
"Nivolumab_2017_p077_ar_8846", "Nivolumab_2017_p078_ar_8864", 
"Nivolumab_2017_p084_ar_8850", "Nivolumab_2017_p085_ar_8829", 
"Nivolumab_2017_p092_ar_8867", "Nivolumab_2017_p101_ar_8834", 
"EA632174", "EA632234", "EA632688", "EA632802", "EA639069", "EA639120", 
"EA639131", "G109543_RCCBMS_00114_T_v1_RNA_OnPrem", "G109543_RCCBMS_00147_T_v1_RNA_OnPrem"
), class = "data.frame")

解决方案

核心思路是将两个数据集整理为长格式,添加分组标识区分两个模型的Group 0,再统一拟合生存曲线并绘制。

步骤1:整理数据集

给每个模型的Group 0数据添加模型标识,合并为单一数据框:

library(dplyr)
library(survival)
library(survminer)

# 提取并整理模型1的Group 0数据
tme_0_clean = tme_0 %>%
  mutate(model_group = "Model1_Group0") %>%
  select(model_group, survival_time, survival_status)

# 提取并整理模型2的Group 0数据
nontme_0_clean = nontme_0 %>%
  mutate(model_group = "Model2_Group0") %>%
  select(model_group, survival_time, survival_status)

# 合并两个数据集
combined_data = bind_rows(tme_0_clean, nontme_0_clean)

步骤2:拟合生存曲线

基于合并后的数据集,按模型分组拟合生存曲线:

# 创建统一的生存对象
surv_obj = Surv(time = combined_data$survival_time, event = combined_data$survival_status)

# 按模型分组拟合生存曲线
fit_combined = survfit(surv_obj ~ model_group, data = combined_data)

步骤3:绘制合并后的生存曲线

用ggsurvplot绘制包含两条曲线的图,设置图例、颜色等参数:

ggsurv_combined = ggsurvplot(
  fit_combined,
  data = combined_data,
  risk.table = TRUE,
  pval = TRUE,  # 自动计算两组的log-rank检验p值
  conf.int = TRUE,
  legend.title = "Groups",
  legend.labs = c("Model1 Group0", "Model2 Group0"),
  palette = c("blue", "red"),
  risk.table.y.text.col = TRUE,
  risk.table.y.text = FALSE
)

# 显示图形
print(ggsurv_combined)

重叠样本处理(可选)

如果同一个样本在两个模型的Group 0中都存在,可根据行名去重避免重复统计:

# 添加样本ID列(行名)
tme_0_clean = tme_0 %>%
  mutate(sample_id = rownames(tme_0), model_group = "Model1_Group0") %>%
  select(sample_id, model_group, survival_time, survival_status)

nontme_0_clean = nontme_0 %>%
  mutate(sample_id = rownames(nontme_0), model_group = "Model2_Group0") %>%
  select(sample_id, model_group, survival_time, survival_status)

# 合并后去重(保留每个样本的一条记录)
combined_data_unique = bind_rows(tme_0_clean, nontme_0_clean) %>%
  distinct(sample_id, .keep_all = TRUE)

# 用去重后的数据拟合和绘图
surv_obj_unique = Surv(time = combined_data_unique$survival_time, event = combined_data_unique$survival_status)
fit_unique = survfit(surv_obj_unique ~ model_group, data = combined_data_unique)

ggsurv_unique = ggsurvplot(
  fit_unique,
  data = combined_data_unique,
  risk.table = TRUE,
  pval = TRUE,
  conf.int = TRUE,
  legend.title = "Groups",
  legend.labs = c("Model1 Group0", "Model2 Group0"),
  palette = c("blue", "red")
)
print(ggsurv_unique)

内容的提问来源于stack exchange,提问作者Programming Noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 21:40:54