复现一篇16分的seer数据库文章:列线图风险评分+最佳阈值风险分层+生存分析曲线
列线图,又称诺莫图(Nomogram),它是建立在回归分析的基础上,使用多个临床指标或者生物属性,然后采用带有分数高低的线段,从而达到设置的目的:基于多个变量的值预测一定的临床结局或者某类事件发生的概率。列线图(Nomogram)可以用于多指标联合诊断或预测疾病发病或进展。
近些年来在高质量SCI临床论文中用的越来越多。列线图将回归模型转换成了可以直观的视图,让结果更容易判断,具有可读性。

目前,通过列线图的风险评分对患者结局进行预测已经成为了一种发文方式,今天介绍一篇seer数据库16分的文章中的列线图风险评分+最佳阈值风险分层+生存分析曲线,就是下面这篇文章。

作者介绍了一个低级别子宫内膜间质肉瘤 (LG-ESS) 是一种罕见的恶性间充质肿瘤,这种肿瘤目前没有很好的预后评估方式,目前国际妇产科联合会(FIGO)分期系统最常用于ESS患者的预测,但是这种预测方法效果并不好,所以有了这预测模型篇文章。
这是个典型的预测模型文章,作者做了列线图,校准曲线,决策曲线,NRI,IDI,C指数,时间相关ROC等,这些我都不打算介绍,公众号已经有很多文章了。主要介绍作者通过列线图评分后,通过最佳阈值切点进行分析分层,分成低中高三组,再做KM曲线,我觉得这个是个不错的思路。
下面我来演示一下,使用我好多年前讲解seer数据库时候用的一个数据,好像是肝癌的。我先导入数据
setwd("E:/公众号文章2025年/列线图+风险分层IF16分")
data<-read.csv("1.csv",sep=',',header=TRUE)
dput(names(data))
data2<-subset(data,data$Imputation_==1)
var<-c("sex", "time", "rezult1", "status", "race",
"Subtype", "nodes", "tumor.size", "extension", "lymph.nodes",
"age", "age")
data2<-data2[,var]
rm(data)

这个data2是等下用来分析的数据,如上所示,status是结局变量,其他都是协变量
咱们先把分类变量转成因子
library(MASS)
library(survival)
data2<-na.omit(data2)
data2$sex<-as.factor(data2$sex)
data2$rezult1<-as.factor(data2$rezult1)
data2$race<-as.factor(data2$race)
data2$Subtype<-as.factor(data2$Subtype)
作者使用了逐步回归和先单后多两种方式来帅选变量,其实差不多的,逐步回归可以用MASS包的stepAIC函数来进行分析
full.model <- coxph(Surv(time, status==1) ~ . , data = data2)
summary(full.model) # 查看模型摘要
step.model <- stepAIC(full.model, direction = "both") # 执行逐步回归
summary(step.model) # 查看逐步回归后的模型摘要

接下来就是先生成COX回归模型
library(rms)
dd<-datadist(data2)
options(datadist="dd")
model1 <- cph(Surv(time, status==1) ~ sex+ rezult1+race+Subtype+nodes+tumor.size+
lymph.nodes+age+age,y=T, surv=T, data = data2)
生成预测概率函数
surv <- Survival(model1)
生成列线图函数,这里我要说一下maxscale=100等于把分数扩张了10被,这样的分数就会上百了,对于一些大数据可以这样用
nom <- nomogram(model1, fun=list(function(x) surv(36, x), function(x) surv(60, x)),
lp=F, funlabel=c("3-year survival", "5-year survival"),
maxscale=100, fun.at=c(0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.6, 0.5))
绘图
library(scitable)
require(base64enc)
require(httr)
require(R6)
scinom(nom,username=username,token=token)

我们这里注意一下最大总分是300分,下面我们来寻找截点,对于3分类的截点,文章是使用X-tile软件找的,我这里使用我自己编写的scinompoints函数来寻找,一句话代码就行,非常方便
out<-scinompoints(data = data2,nom=nom,fit = model1,y="status",time="time",username=username,token=token)
data这里填入数据,nom这里填入你的列线图,fit这里是模型,y这里填入结局,x这里默认是评分,你想改其他的话也要填入,time这里是时间
大概要跑10分钟,时间更具你的数据量和电脑速度来定,结果在OUT这里

我们把数据提取出来
dtpv<-out[["out2"]][["dtpv"]] #最小P值数据
dt<-out[["out2"]][["dt"]] #P值数据
data<-out[["out2"]][["data"]] #绘图和分析数据
dt这里有所有相关截点的数据,HR1表示中和第比较,HR2表示高和低比较
Data这里是最后生成的分析和绘图数据,你可以手动绘图,或者使用函数生成的图片,函数生成的图片就是OUT里面的p
out[["p"]]

结合刚才的数据表,我们可以知道虽然中和低离得很近,也是有区别的,只是没有高的这么明显

根据截点绘制新的列线图
scinom(nom,username=username,token=token,cutpoint = c(0,26,79,300))

最后我总结一下,我们已经完美的复现了作者列线图+评分风险分层+KM曲线,但是这个数据中,随着评分升高,生存分线明显降低,我觉得RCS曲线也可以考虑一下。
复现一篇16分的seer数据库文章:列线图风险评分+最佳阈值风险分层+生存分析曲线
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)