作者:麦子

转载请注明:解螺旋·临床医生科研成长平台

上期我们介绍了一个诊断或风险预测模型的评价指标,重新分类指数(Net reclassification index)。主要介绍了一些概念和运用,今天我们就来解决一下技术问题,怎么算。想来想去,我觉得计算这个东西还是R比较威武。

话说恰好前两天在知乎上看到某位生物学大大发了这么一张图——

啊呀啊哟!不服啊不服哎!可是想来好像又好有道理^(00)^

今天是R语言代码的盛(暴)宴(击),除了NRI的运算,还有蛮多预处理的操作,在哪都能用得着。大家做好战斗准备。

R里有2个包专事计算NRI,分别为nricens和PredictABEL。从最后结果来说,nricens计算出来的是绝对NRI,PredictABEL则为相对NRI。但我们已经知道计算原理了呀,而且它们都能生成新旧模型分类的对照表,所以其实只用其中一个包就都可以计算了。

不过它们还是有一些小小差异,我们就以logistic回归模型为例,分别看一下这两个包,供大家参考选择。Cox模型参数较多也较复杂,但我相信你看完这篇的讲解就能看懂帮助文档中的cox案例,算是留个小作业给你吧~

拟合模型

先用一份示例数据做个模型。这是survival包里带有的一份梅奥诊所的数据,记录了418位患者的临床指标,观察这些因素与原发性胆汁性肝硬化(PBC)的关系。其中前312位参加了RCT,其他的只参加了观察队列。

我们用前312份样本,做个预测2000天时间点上死亡与否的模型。先载入这份数据看一下。

library(survival)

### logistic回归

egData <- pbc[1:312,]

(点击看大图)

做一个logistic回归,我们需要一个结局事件作为因变量,它必需是个分类变量;其次需要若干自变量,它们可以是分类也可以是连续。

这个表中的结局是status,0 = 截尾(删失),1 = 接受移植,2 = 死亡。研究目的“死亡与否”是个二分类变量,所以要做些变换。

再看time一栏,有的不够2000天,这些样本要么是没到2000天就死亡了,要么是删失了。我们要删掉2000天内删失的数据。

egData = egData[egData$time > 2000 |

(egData$time < 2000 & egData$status == 2),]

“[ ]” 表示筛选条件,| 表示“或”,& 为“和”。所以条件句就是egData中的time一列大于2000的保留,或小于2000但同时状态为死亡的也保留。最后一个“,”别忘了,其在条件句的前面表示对列进行选择,在其后表示选择行。

选好后做一个event向量,把status的三个状态变成死亡 = 1, 未死亡 = 0。

event = ifelse(egData$time < 2000 & egData$status == 2, 1, 0)

ifelse (test, yes, no)大法好啊,前面一个test是逻辑判断句,其值为真时返回yes的值,为假时返回no的值。所以本句中test就是当time<2000,且status为2(死亡)时,记为1,否则为0。

然后把event合并入原来的表格。

egData = cbind(egData,event)

cbind()是以列合并,另有rbind()以行合并。这样event就成了最后一列,为结局事件。

然后选择模型的自变量(predictors)。太多了,选取其中几个示例。就以年龄、胆红素、白蛋白为旧模型(standard),三者加上一个凝血酶原时间为新模型(new)。

一般做logistic回归是用glm(因变量 ~ 自变量1 + 自变量2 + …… +自变量n,family = binomial('logit'),data = 数据表),但如果自变量较多的话,前面那个运算式就会很长很长,万一这些自变量还是基因名或编号,就很想死了。所以顺便讲一个简化的办法,即把那一串先写成formula。

fml.std <- as.formula(paste('event~',

paste(colnames(egData)[c(5,11,13)],

collapse = '+')))

这里有好几层函数,paste() 会把括号中的元素粘贴起来,collapse是其中的间隔。colnames() 是获取表格的列名,[]中的数值向量为所选择的列序号。这样如果是一个超大表格,你选中第10~70列还可以写成“10:70”。

好了,同样写出新模型的formula:

fml.new <- as.formula(paste('event~',

paste(colnames(egData)[c(5,11,13,19)],

collapse = '+')))

可以查看一下,新模型的formula写成这个效果:

然后像上边说的那样用glm()拟合两个模型。

mstd = glm(fml.std, family = binomial('logit'),

data = egData, x=TRUE)

mnew = glm(fml.new, family = binomial('logit'),

data = egData, x=TRUE)

这样一长串运算式用刚才命名好的fml.std和fml.new代替就好了。x=TRUE是将来用nricens包计算时要求用到的,表示输出结果中是否包含所用到的数据表,平时可以不写。

模型就这样做完了~ 先不急着计算NRI,先看看它的总体情况。

summary(mstd)

运行这句就得到该模型的描述特征。

残差、相关系数、各个自变量的统计显著性等,注意倒数第二行的AIC,就是上一期提到的赤池信息准则,表示模型校准度,很少有人汇报呢。

可以用同样的方法看看新模型。这里就-不展开了,进入下一环节。

NRI的计算

• 先看nricens包的方法。

library(nricens)

NRI <- nribin(mdl.std = mstd, mdl.new = mnew,

updown = 'category',cut = c(0.3,0.6),

niter = 10000,alpha = 0.05)

填上新旧两个模型。Cut是判断风险高低的临界值,现在我们写了2个,也就是0~29%为低风险,30%~59%为中风险,60%~100%为高风险。现实中可以查阅相关文献进行设置,预测风险达到多少需要怎样干预之类的。

Updown为定义一个样本的风险是否变动的方式,category是指分类值,即我就熟悉的低、中、高风险,另有一种diff,为连续值。选diff时,cut就设1个值,比如0.02,即认为当预测的风险在新旧模型中相差2%时,即被认为是重新分类了。这种方法用的比较少。

后面几个参数就比较有意思了,niter为重复取样的次数,即boostrap方法,不做的话将其设为0就好了;做的话建议至少1000次,这也是默认值,但我(读书少)见过的研究都10000次。然后将统计显著性alpha设为0.05。

这样就可以看到输出的结果:

如果不做bootstrap,就是这个结果。有重新分类情况的详表,最后是NRI和各种变动的概率。第一个NRI如前所述,是绝对NRI,大家可以根据之前的知识和上边的详表自己计算验证一下,此时可手动计算出相对NRI。其他指标随便看看。

如果做了bootstrap,就会多出一个表:

因为做了10000次重复取样,相当于有10000个NRI,于是就有了标准误和置信区间,刚才我们设alpha = 0.05,所以后面的Lower和Upper就是95%置信区间的下界和上界。

同时,做不做bootstrap都会得到一张图,表示各数据点在新旧模型中的分布。

默认的Case和Control标签我觉得不太严谨,Case代表结局事件中编号为“1”的组,也就是发生了结局(死亡),Control为“0”,未发生。其实是positive和negative比较贴切吧。反正就这个意思。这张图也和重新分类表的意思差不多,看看就好。

• 再看PredictABEL包的做法

library(PredictABEL)

pstd <- mstd$fitted.values

pnew <- mnew$fitted.values

先把两个模型中的预测风险值提出来,也就是模型中的fitted.value。这个包只能从预测风险计算,刚才的nricens包可以用模型,也可以用预测风险(把mdl.std和mdl.new参数换成p.std和p.new)。

reclassification(data = egData,cOutcome = 21,

predrisk1 = pstd,predrisk2 = pnew,

cutoff = c(0,0.30,0.60,1))

cOutcome是结局事件的列序号,刚才我们不是把event放到最后了么,即第21列,填上。两个预测风险值也相应填上。这里的cutoff跟刚才的不一样,还要填上前面的0和后面的1,成为完整的0~100%的区间。

然后得到一个重新分类表:

跟上边nricens做的差不多了。不过这个包没有bootstrap的选项。

接着看下面的结果,这里的分类NRI是咱们上回说的相加NRI,同样可以根据上一期的知识手动计算一下。记得咱们并没有设置bootstrap吧?可这里也有个95%置信区间,只是内部调用了一个更为简陋的只能计算连续NRI的improveProb()函数做的,而且连续变化的临界值也不太透明,遂不管了。

最后还有个IDI是指,发生和未发生结局事件样本的平均预测风险差异,在新模型中提高了0.44%。

延伸、总结和比较

这两个包当然各有优劣。nricens计算时可控制的参数较多,汇报起来显得华丽一些。PredictABEL计算结果则多了个IDI和大家喜闻乐见的p值。但也有学者表示,两个模型的差异未必要求p<0.05。

PredictABEL包还有很多有用的功能,比如可以做Hosmer- Lemeshow校准曲线,当然也附送p值(此处没贴出来):

区分度箱形图:

两个模型的ROC曲线:

这都是评价一个模型很有价值的参考。

风险预测模型评价第二弹:NRI的R语言计算相关推荐

  1. R语言:计算各种距离

    R语言:计算各种距离 MATLAB 版本的 http://blog.csdn.net/sinat_26917383/article/details/52101425 PYTHON版本的 http:// ...

  2. R语言--计算各种距离

    MATLAB 版本的 http://blog.csdn.net/sinat_26917383/article/details/52101425 PYTHON版本的 http://book.2cto.c ...

  3. R语言计算线性回归的最小二乘估计

    R语言计算线性回归的最小二乘估计 全称:线性回归的最小二乘法(OLS回归),ordinary least square,字面翻译:普通最小平方: 内容:包括三个部分:简单线性回归.多项式回归.多元线性 ...

  4. R语言计算资本资产定价模型(CAPM)中的Beta值和可视化

    原文链接:http://tecdat.cn/?p=22588 今天我们将计算投资组合收益的CAPM贝塔.这需要拟合一个线性模型,得到可视化,从资产收益的角度考虑我们的结果的意义. 简单的背景介绍,资本 ...

  5. R语言计算曼哈顿距离(Manhattan Distance)实战:计算两个向量的曼哈顿距离、dist函数计算矩阵中两两元素的曼哈顿距离

    R语言计算曼哈顿距离(Manhattan Distance)实战:计算两个向量的曼哈顿距离.dist函数计算矩阵中两两元素的曼哈顿距离 目录 R语言计算曼哈顿距离(Manhattan Distance ...

  6. R语言计算杰卡德相似系数(Jaccard Similarity)实战:自定义函数计算Jaccard相似度、对字符串向量计算Jaccard相似度、将Jaccard相似度转化为Jaccard距离

    R语言计算杰卡德相似系数(Jaccard Similarity)实战:自定义函数计算Jaccard相似度.对字符串向量计算Jaccard相似度.将Jaccard相似度转化为Jaccard距离 目录 R ...

  7. R语言计算平均值的标准误差(standard error of the mean):自定义函数计算平均值的标准误差、使用plotrix包的std.error函数计算平均值的标准误差

    R语言计算平均值的标准误差(standard error of the mean):自定义函数计算平均值的标准误差.使用plotrix包的std.error函数计算平均值的标准误差 目录

  8. R语言计算回归模型每个样本(观察、observation、sample)的DFFITS度量实战:忽略单个观察(样本)时,回归模型所做的预测会发生多大的变化

    R语言计算回归模型每个样本(观察.observation.sample)的DFFITS度量实战:忽略单个观察(样本)时,回归模型所做的预测会发生多大的变化 目录

  9. R语言计算回归模型每个样本(观察、observation、sample)的杠杆值(leverage)实战:如果一个样本的预测变量比其他样本的预测变量值更极端,那么被认为具有很高的杠杆作用

    R语言计算回归模型每个样本(观察.observation.sample)的杠杆值(leverage)实战:如果一个样本的预测变量比其他样本的预测变量值更极端,那么被认为具有很高的杠杆作用 目录

最新文章

  1. XML与Webservices相关的安全问题概述
  2. FineReport搭建物流报表平台的解决方案
  3. 《如何像证券交易员一样思考和行动》_学习笔记
  4. TFOD:基于TFOD API的官方模型案例对图片进行目标检测
  5. qgridlayout 滚动时固定第一行_滚动直线导轨副的安装技术
  6. wxWidgets:wxAny类用法
  7. java 布尔逻辑运算符_Java运算符
  8. Javascript使用技巧-提高工作效率
  9. nginx 之 proxy_pass详解
  10. javaJSON字符串转换实体类
  11. Win10家庭版禁用系统更新方法汇总及问题解决
  12. 阿里云ICON全部下载
  13. 第二章 软件项目立项与规划
  14. 适应浏览器自带断点下载
  15. star法则 java_STAR法则(示例代码)
  16. 运算放大器节点电压方程_区分运算放大器和电压比较器
  17. PHP毕业设计项目作品源码选题(9)学校校园教师排课系统毕业设计毕设作品开题报告
  18. php本地环境搭建教程,用 phpstudy 搭建本地 php 环境及安装 wordpress 教程
  19. 【目标检测实验系列】使用yolov3 spp训练西工大遥感数据集NWPU VHR-10(包括如何将NWPU VHR-10转为VOC格式和yolov3 spp实验调试的详细步骤,且附上训练完的权重文件)
  20. Android用Canvas画钟表仪

热门文章

  1. 哈夫曼树的构造及C++代码实现
  2. 工欲善其事,必先利其器之—利用网上在线工具—多个地点Ping服务器以检测服务器响应情况
  3. 2JS-操作BOM对象
  4. 树莓派html5播放器,QT+树莓派实现一个简单的播放器
  5. configure报错
  6. android五大布局的作用,Android五大布局与实际应用详解
  7. 身份认证技术的产业发展
  8. 计算机二级考试没过能重考吗,计算机二级能重复考吗
  9. 批处理(batch)教程
  10. docker如何查看宿主机到容器端口映射