分享

两Cox模型预测能力的比较:NRI[净重分类改善指数]

 Memo_Cleon 2024-03-09 发布于上海

净重分类改善指数(Net Reclassification Improvement Index,NRI)的基本概念参见两个logistic模型预测能力的比较:NRI[净重分类改善指数]。与之不同的是,在生存数据一般会存在删失的情况,两个生存模型NRI的计算需要预先指定一个时间点。

相比AUCNRI更为敏感。其不足是基于风险分类的NRI依赖于类别的选择和数量,分类标准或分类水平都会影响到NRI结果。基于风险分类的NRI是根据预测风险和某种标准将患者进行分类来确定事件组和对照组中向上(up)和向下(down)重分类的数量然后来计算NRI的,但实际上分为几类并不是必须的,只要能确定向上和向下重分类的数量即可。
在汇报分类NRI结果时,一般需要同时汇报事件NRI非事件NRI进行更全面的解释。
在进行风险分类时,分类标准最好是已经存在的比较通用的标准。一般不建议使用超过3个以上的类别,除非有足够的理由。如果你觉得需要一个比三类更细的分类,无类别或者连续性NRIcategory-less or continuous NRI提供了一个更好的选择。
连续性NRI是更为客观的衡量标准,因此在确实存在先验类别的情况下,连续NRI仍然仍然值得报告,以便可以与其模型进行比较。
1】数据导入,数据集拆分

library(survival)

GBSG<-gbsg

GBSG$grade<-factor(GBSG$grade)

library(caret)

library(ggplot2);library(lattice)

set.seed(20240229)

split<-createDataPartition(GBSG$status,p=0.7,list=FALSE)

split<-as.vector(split)

trainset<-GBSG[split,]

testset<-GBSG[-split,]

2】建立Cox模型并获得计算NRI需要的一些参数

agemenosizenodesgrade五个变量建立的模型为旧模型,利用全子集回归获得4个变量sizenodespgrhormon建立的模型为新模型。

library(survival)

BC.std<-coxph(Surv(rfstime,status)~age+meno+size+nodes+grade,data=trainset,x=TRUE)

BC.new<-coxph(Surv(rfstime,status)~size+nodes+pgr+hormon,data=trainset,x=TRUE)

Pstd.e3Y.train<-1-summary(survfit(BC.std,newdata=trainset),times=365.25*3)$surv[1,]

#模型BC.std对训练集中每个个体在3年内发生结局事件的的预测概率(患病风险)Pstd.e3Y.test<-1-summary(survfit(BC.std,newdata=testset),times=365.25*3)$surv[1,]

#模型BC.std对测试集中每个个体在3年内发生结局事件的的预测概率(患病风险)

Pnew.e3Y.train<-1-summary(survfit(BC.new,newdata=trainset),times=365.25*3)$surv[1,]

#模型BC.new对训练集中每个个体在3年内发生结局事件的的预测概率(患病风险)

Pnew.e3Y.test<-1-summary(survfit(BC.new,newdata=testset),times=365.25*3)$surv[1,]

#模型BC.new对测试集中每个个体在3年内发生结局事件的的预测概率(患病风险)

训练集的预测风险可以直接通过get.risk.coxph::nricens来获取,但该函数不能获得测试集的预测风险:

library(nricens)

Pstd.e3Y.train<-get.risk.coxph(BC.std, 365.25*3)

Pnew.e3Y.train<-get.risk.coxph(BC.new, 365.25*3)

Xstd.train<-model.matrix(~age+meno+size+grade+nodes,data=trainset)[,-1]

#训练集中模型BC.std的预测变量矩阵。该矩阵中含有一个三水平分类变量grade,后面我们计算NRI的函数nricens::nricens不允许有因子变量,通过model.matrix()可将因子变量设置为哑变量并保持连续变量不变来创建模型矩阵,[,-1]是从 model.matrix 的输出中模型矩阵删除Intercept项。直接使用命令as.matrix() 只能将因子变量的赋值转换为数值格式,后面运行程序时会报错

Xstd.test<-model.matrix(~age+meno+size+grade+nodes,data=testset)[,-1] #测试集中模型BC.std预测变量矩阵

Xnew.train<-as.matrix(subset(trainset,select=c(size,nodes,pgr,hormon))) #训练集中模型BC.new的预测变量矩阵
Xnew.test<-as.matrix(subset(testset,select=c(size,nodes,pgr,hormon))) #测试集中模型BC.new预测变量矩阵

3】计算两个Cox模型的NRInricens::nricens

nricens(time=NULL,event=NULL,mdl.std=NULL,mdl.new=NULL,z.std=NULL,z.new=NULL,p.std=NULL,p.new=NULL,t0=NULL,updown="category",cut=NULL,point.method="km",

niter=1000,alpha=0.05,msg=TRUE)

#time指定随访时间;event指定结局状态,0为删失,1为发生结局事件;mdl.stdmdl.new分别指定标准模型和新模型的coxphsurvreg对象,在拟合Cox或参数生存模型时其x参数需要设置为x=TRUE(预测变量需要从glm对象中提取);z.stdz.new分别指定标准模型和新模型的预测变量矩阵,不允许有因子、字符和缺失值p.stdp.new分别指定标准模型和新模型的预测风险向量;t0指定评估时间点;updown指定确定updown的方法,默认为"category",计算的是基于风险分类的NRI,取值"diff",将计算基于风险差的NRIcut指定一个标量或向量,作为确定updown的预测风险(风险类别或风险差)的界值,标量(1个值)用于二分类或风险差,向量(多个值)可用于多分类。连续性NRI是风险差的一种特殊类型,可以通过指定updown="diff"cut=0来实现point.method指定点估计方法,"km" 采用Kaplan-Meier (KM)法,"ipw"采用逆概率加权 (IPW) 估计;niter自主抽样的次数,具体使用的是百分位自助式方法,用于计算置信区间,默认1000次,若取值为0则不计算置信区间;,alpha指定α值,1-α置信区间将被计算;msg指定是否显示计算过程

#指定以下任何一组参数都可以计算NRI(mdl.std,mdl.new);(time,event,z.std,z.new);(time,event,p.std,p.new)指定参数mdl.stdmdl.new:生存时间、结局事件、标准模型和新模型的预测变量都将从模型中提取。但如果也指定参数timeevent,则使用timeevent指定的生存时间和结局事件而不是从coxphsurvreg对象中提取;指定参数timeeventz.stdz.new,直接利用预测变量和生存时间、结局变量拟合一个标准模型和一个新的预测模型。这种模式下,z.stdz.new需要使用同一个数据集;指定参数timeevent,p.stdp.new直接使用预测风险来计算NRI,该模式下自助抽样时并未执行预测模型的拟合,可用于外部数据或交叉验证的验证研究。这种模式下,p.stdp.new也需要使用同一个数据集

library(nricens)

set.seed(20240229)

nricens(mdl.std=BC.std,mdl.new=BC.new,t0=365.25*3,updown="category",cut=c(0.2,0.5))

#0-0.2为低风险;0.2-0.5中风险;0.5-1高风险

nricens(time=trainset$rfstime,event=trainset$status,z.std=Xstd.train,z.new=Xnew.train,t0=365.25*3,updown="category",cut=c(0.2,0.5))
nricens(time=trainset$rfstime,event=trainset$status,p.std=Pstd.e3Y.train,p.new=Pnew.e3Y.train,t0=365.25*3,updown="category",cut=c(0.2,0.5))
以上三种方法会获得相同的结果因置信区间的计算采用了Bootstrap,发生了随机抽样,为获得置信区间结果的可重复性,在每次运行计算NRI的命令前可通过set.seed设置相同的随机种子。

TotalCaseControl分别为481159234,表示全部研究对象为481人,3年内发生结局事件的病例159人,没有发生结局事件的对照组234人。Total中除了CaseControl外,还有随访到3年时删失的人数481-159-234=88人。

三个表分别是针对所有研究对象、病例组和对照组两个模型的分类情况。因为涉及到删失数据,直接通过表格中的向上和向下数据来估计NRI并不合适。NRI点估计有Kaplan-Meier (KM)法、逆概率加权法(IPW)、半参数法(SEM)、平滑逆概率加权法(SmoothIPW)等,不同的方法计算的结果会有差异。nricens函数中提供了KMIPW法,可通过参数point.method进行设置。

NRI点估计结果NRINRI+NRI-分别对应的就是相加NRI、病例组NRI和对照组NRI

在预测3年的生存结局上,与标准模型相比,新模型重分类正确的比例提高20.22%,其中对阳性结局重分类正确的比例提高13.74%,对阴性结局重分类正确的比例提高6.48%

NRI+=Pr(Up|Case)-Pr(Down|Case)NRI-=Pr(Down|Ctrl)-Pr(Up|Ctrl)

注:Pr(Up|Case)表示利用新模型对病例组进行重分类,风险类别提高的那些病例所占的比例;Pr(Down|Case)表示利用新模型对病例组进行重分类,风险类别降低的那些病例所占的比例;Pr(Down|Ctrl)表示利用新模型对对照组进行重分类,风险类别降低的那些病例所占的比例;Pr(Up|Ctrl)表示利用新模型对对照组进行重分类,风险类别升高的那些病例所占的比例。

其后是利用Bootstrap法估计的置信区间。

NRI图中虚线表示通过cut参数设置的界值,红色、黑色和浅蓝色点分别表示病例组、对照组和删失数据采用标准模型和新模型预测风险情况。理论上,如果两个模型的区分度还不错,预测能力差别不大,则数据点会分布在y=x的直线附近,且红点多在右上,黑点多在左下,删失点则随机。如果新模型的预测能力好于标准模型,则红点普遍向上偏,黑点普遍向下偏。
nricens{nricens}计算的NRI并未给出显著性指标P值,但通过95%的置信区间是否包含0可以大体判断其显著性,本例NRI未包含0,其P<0.05,而NRI+NRI-95%CI均包含了0,因此其P值均>0.05

标准模型和新模型对测试集3年发生结局事件的的分类变化情况:

set.seed(20240229)

nricens(time=testset$rfstime,event=testset$status,p.std=Pstd.e3Y.test,p.new=Pnew.e3Y.test,t0=365.25*3,updown="category",cut=c(0.2,0.5))

新模型对训练集的5年预测结果按界值0.4进行二分类的重分类变化情况:
set.seed(20240229)
nricens(mdl.std=BC.std,mdl.new=BC.new,t0=365.25*5,updown="category",cut=0.4)

新模型对训练集的3年预测结果按差值15%进行二分类的重分类变化情况:

set.seed(20240229)

nricens(mdl.std=BC.std,mdl.new=BC.new,t0=365.25*3,updown="diff",cut=0.15)

#updown设置为diff时,cut的取值只能1个,本例设置0.15表示当新模型预测的风险和旧模型相差0.15时,认为是重新分类

全部研究对象为481人,病例组159人,对照组234人;新模型比标准模型预测风险高0.15以上共35人,其中病例组14人,对照组15人;新模型比标准模型预测风险低0.15以上的共54人,其中病例组7人,对照组35人。

新模型对训练集的5年预测结果按连续性NRI重分类变化情况:

set.seed(20240229)
nricens(mdl.std=BC.std,mdl.new=BC.new,t0=365.25*5,updown="diff",cut=0)

模型预测能力的比较:IDI[综合判别改善指数]一文中,在计算两个Cox模型IDI时结果同时输出了连续NRI的结果。我们发现IDI.INF::survIDINRInricens::nricens计算的连续NRI结果并不一致。原因有①导入数据划分训练集和测试集时使用了不同的随机种子,所以建模时采用的数据集并不相同;②survIDINRI包中,连续性NRI定义为1/2 NRI(>0),即普通NRI的一半NRI一般定义为事件组NRI和对照组NRI的和,取值一半相当于把两个子组进行平均,这样的NRI的值域就定义在[-1,1]之间了。NRI(>0)表示连续NRI(无类别NRI),NRI(0.5)表示两类别NRI,类别划分界值为0.5,而NRI(0.3,0.8)表示三分类NRI,分类界值是0.30.8;③两生存模型NRI估计有不同的方法,KMIPWSEMSmoothIPW,采用不同的方法结果会有出入。本例如果采用IPW法,与survIDINRI计算的结果就非常接近了(NRI:survIDINRI≈1/2nricens):

nricens(mdl.std=BC.std,mdl.new=BC.new,t0=365.25*5,updown="diff",cut=0,point.method="ipw")

— END —

@_@

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多