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

R语言survival包绘制生存曲线始终为直线的问题咨询

R生存分析绘制生存曲线出现直线异常的排查与修正方案

问题现象

使用R开展生存分析、绘制生存曲线时,代表各年度生存概率的曲线未呈现预期的阶梯式下降、最终稳定在55%左右生存概率的形态,反而显示为直线。
错误结果示例图

问题根因排查

  • 数据类型错误:data_2013中生存时间Years_Diff_Surg_Death、结局变量Survival均存储为字符串类型,survfit函数无法正确识别数值型时间、二分类结局,生存概率计算逻辑异常。
  • 数据构造长度不匹配:data_2014中YEARS_OF_SURGERY向量长度为7,其余列(生存时间、结局)长度仅为6,数据框自动循环补全值导致分组错乱,生存时间计算完全偏离真实值。
  • 变量名拼写错误:拟合fit_2017时,公式中分组变量写为YEARS_OF_SURVERY,和数据集中实际列名YEARS_OF_SURGERY不一致,模型拟合失败。
  • 时间单位与坐标轴范围不匹配:所有年度子数据集中,大部分删失样本的生存时间值为30+(对应单位为月而非年),设置xlim=c(0,5)仅展示前5年区间时,大部分删失点都在绘图区间外,区间内事件点极少,就会呈现近似直线的形态。
  • 合并绘图参数错误:ggsurvplot_combine调用时传入了不存在的数据集data_ECV,且传入的拟合对象列表中不同fit的分组变量水平混杂,无法正确映射阶梯线。

修正后可复现代码

library(survival)
library(survminer)
library(dplyr)
library(ggplot2)
library(readxl)
library(tidyverse)

# 1. 统一构造数据集,修正类型、长度、拼写错误,统一时间单位(月转年)
data_all <- data.frame(
  Years_Diff_Surg_Death = c(8.919917864, 8.895277207, 8.881587953, 8.821355236, 8.728268309, 8.709103354)/12,
  Survival = c(1L, 0L, 1L, 1L, 1L, 1L),
  YEARS_OF_SURGERY = "all"
)

data_2013 <- data.frame(
  Years_Diff_Surg_Death =  as.numeric(c("36.99383984", "2.584531143", "36.91991786", "36.89527721", "36.88158795", "36.82135524"))/12,
  YEARS_OF_SURGERY = rep("2013",6),
  Survival = as.integer(c("1","0", "1", "1", "1", "1"))
)

# 修正data_2014向量长度不匹配问题
data_2014 <- data.frame(
  Years_Diff_Surg_Death = c(0.542094456, 5.196440794, 35.95619439, 35.91786448, 35.86584531, 35.8275154)/12,
  YEARS_OF_SURGERY = c("2014", "2014", "2015", "2014", "2014", "2014"),
  Survival = c(0L, 0L, 1L, 1L, 1L, 1L)
)
                        
data_2015 <- data.frame(
  Years_Diff_Surg_Death = c(34.4476386, 34.25598905,0.621492129, 34.38740589, 34.33264887, 1.081451061)/12,
  YEARS_OF_SURGERY = rep("2015",6),
  Survival = c(1L, 1L, 0L, 1L, 1L, 0L)
)
                                                                           
data_2016 <- data.frame(
  Years_Diff_Surg_Death = c(2.902121834, 0.950034223, 33.9301848, 33.91101985, 33.87268994, 33.85352498)/12,
  YEARS_OF_SURGERY = rep("2016",6),
  Survival = c(0L, 0L, 1L, 1L, 1L, 1L)
)
                                                
# 修正变量名拼写问题
data_2017 <- data.frame(
  Years_Diff_Surg_Death = c(32.99110198, 3.348391513, 32.95277207,32.91170431, 32.87611225, 0.791238877)/12,
  YEARS_OF_SURGERY = rep("2017",6),
  Survival = c(1L, 0L, 1L, 1L, 1L, 0L)
) 

# 合并所有数据集用于组合绘图
data_comb <- bind_rows(data_2013, data_2014, data_2015, data_2016, data_2017, data_all)

# 统一拟合模型
fit_all <- survfit(Surv(Years_Diff_Surg_Death, Survival) ~ 1, data = data_all)
fit_2013 <- survfit(Surv(Years_Diff_Surg_Death, Survival) ~ YEARS_OF_SURGERY, data = data_2013)
fit_2014 <- survfit(Surv(Years_Diff_Surg_Death, Survival) ~ YEARS_OF_SURGERY, data = data_2014)
fit_2015 <- survfit(Surv(Years_Diff_Surg_Death, Survival) ~ YEARS_OF_SURGERY, data = data_2015)
fit_2016 <- survfit(Surv(Years_Diff_Surg_Death, Survival) ~ YEARS_OF_SURGERY, data = data_2016)
fit_2017 <- survfit(Surv(Years_Diff_Surg_Death, Survival) ~ YEARS_OF_SURGERY, data = data_2017)
fit_comb_overall <- survfit(Surv(Years_Diff_Surg_Death, Survival) ~ YEARS_OF_SURGERY, data = data_comb)

# 单组绘图示例
ggsurvplot(fit_all, conf.int = TRUE,
          ylim = c(0,1),
          xlim = c(0,5),
          break.x.by = 1,
          title = "术后生存时间曲线",
          xlab = "术后年数",
          legend = "none")

ggsurvplot(fit_2013, conf.int = TRUE,
           ylim = c(0,1),
           xlim = c(0,5),
           break.x.by = 1,
           title = "2013年手术组术后生存曲线",
           xlab = "术后年数",
           legend = "none",
           risk.table = F)

# 其余年度组绘图逻辑同上,替换对应fit对象即可

# 组合绘图,传入存在的合并数据集
ggsurvplot(fit_comb_overall,
                   data = data_comb,
                   xlab = "术后年数",
                   xlim = c(0,5),
                   break.x.by = 1,
                   conf.int = F)

注意事项

  • 生存分析要求生存时间必须为数值型,结局变量必须为0/1编码的数值或逻辑型,禁止存储为字符串/因子类型,否则模型计算会出现不可预期的错误。
  • 构造数据框时所有列向量长度必须一致,否则R会自动循环补全值,直接污染原始数据。
  • 绘图前先确认生存时间的单位和坐标轴范围匹配:如果时间单位是月,要展示5年生存就需要把xlim设为c(0,60),或者提前把时间除以12转换为年单位,避免事件点落在绘图区间外导致曲线形态异常。
  • 调用函数前检查变量名拼写,不要传入不存在的对象/变量。

内容的提问来源于stack exchange,提问作者LIU ZHICHENG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:36:18