QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3039|回复: 0
打印 上一主题 下一主题

[其他资源] 净重新分类指数NRI的计算

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2022-9-12 18:43 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta

    4 U' M; `5 F& |. W; X/ b净重新分类指数NRI的计算; e4 W3 W+ X5 u2 {1 \
    “ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。
    9 k- s& C1 q9 _1 UNRI,net reclassification index,净重新分类指数,是用来比较模型准确度的,这个概念有点难理解,但是非常重要,在临床研究中非常常见,是评价模型的一大利器!
      B' V5 l  [, Y& U, x% {  @+ F7 S' [4 B& v; s, r: M$ C. _
    在R语言中有很多包可以计算NRI,但是能同时计算logistic回归和cox回归的只有nricens包,PredictABEL可以计算logistic模型的净重分类指数,survNRI可以计算cox模型的净重分类指数。4 ~9 ]7 [- G5 @) R/ v
    8 f* i5 M6 i  D
    logistic的NRI
    ) [( Q: v' ?  h6 x- S: x2 dnricens包$ l. P( ^$ w8 f+ V) ]3 @
    PredictABEL包4 l  K/ x: D( C: v* t# C" x0 L
    生存分析的NRI  d; |6 Z3 Q: \+ {. z& |4 R4 ?
    nricens包
    $ k! j! P! |' J" hsurvNRI包
      E' e% f7 B& ologistic的NRI
    . }1 j/ M5 }) Qnricens包
    5 \: a" W6 F  L% a7 w$ N- [5 ?" m#install.packages("nricens") # 安装R包1 a! H* V8 l. I. a* j9 _
    library(nricens)
    4 {5 f, `" }& t$ J8 L1* e" R) G1 u5 u; v
    ## Loading required package: survival
    8 A' S+ O- b2 S# w( o/ R: n( o8 Y1
      f7 c! P5 N/ I& k) X1 W使用survival包中的pbc数据集用于演示,这是一份关于原发性硬化性胆管炎的数据,其实是一份用于生存分析的数据,是有时间变量的,但是这里我们用于演示logistic回归,只要不使用time这一列就可以了。
    - Z- S7 n, D$ @/ o& W: \2 R# X0 [! m% @; a. P
    library(survival)+ @+ ^5 T8 D, X/ L

    % f% N. b0 B* W3 K3 p# 只使用部分数据
    : }# Z- |% k. a: E7 T- @# j( Adat = pbc[1:312,]
    : ?! v, p+ @  k4 xdat = dat[ dat$time > 2000 | (dat$time < 2000 & dat$status == 2), ]; R# ^" d& C# D. @" h" z

    ' ?9 _" O3 |  xstr(dat) # 数据长这样
    ) ]: s( J& S3 a1 C1
    2 b3 l/ R3 ~9 U" Q% u## 'data.frame': 232 obs. of  20 variables:- P! ]' i# o+ P  @
    ##  $ id      : int  1 2 3 4 6 8 9 10 11 12 ...* U3 p- ^( z" a; j, K
    ##  $ time    : int  400 4500 1012 1925 2503 2466 2400 51 3762 304 ...2 Q4 g/ r, U, Y' x4 f. E
    ##  $ status  : int  2 0 2 2 2 2 2 2 2 2 ...
    1 b% _. T5 U- D0 @4 [; M) }6 M. i##  $ trt     : int  1 1 1 1 2 2 1 2 2 2 ...) W: P" o# x# \- w
    ##  $ age     : num  58.8 56.4 70.1 54.7 66.3 .../ J' V! S' E: y# V4 G  q- H
    ##  $ sex     : Factor w/ 2 levels "m","f": 2 2 1 2 2 2 2 2 2 2 ...
    ( @+ s1 m# ]# D7 ~  R9 q' U% K# e4 N##  $ ascites : int  1 0 0 0 0 0 0 1 0 0 ...
    5 h; `5 Z8 P! f% ~6 P0 W##  $ hepato  : int  1 1 0 1 1 0 0 0 1 0 ...
    9 M9 w- ?0 Z4 r- p' N! I##  $ spiders : int  1 1 0 1 0 0 1 1 1 1 ...
      b3 u; g- e2 h. d##  $ edema   : num  1 0 0.5 0.5 0 0 0 1 0 0 ...
    2 I. k* v) u0 J$ Q##  $ bili    : num  14.5 1.1 1.4 1.8 0.8 0.3 3.2 12.6 1.4 3.6 ...( z9 l4 T9 @8 i% b. Z% X
    ##  $ chol    : int  261 302 176 244 248 280 562 200 259 236 ...9 u( l/ C* K9 o% [
    ##  $ albumin : num  2.6 4.14 3.48 2.54 3.98 4 3.08 2.74 4.16 3.52 ...3 R$ {$ }1 X" Q# V# ?6 f
    ##  $ copper  : int  156 54 210 64 50 52 79 140 46 94 .../ ]8 Y1 k; A8 Z' R$ e
    ##  $ alk.phos: num  1718 7395 516 6122 944 ...
    ! M# V. F; _% I. t% p5 v! s##  $ ast     : num  137.9 113.5 96.1 60.6 93 ...3 a( Q5 T* R1 w
    ##  $ trig    : int  172 88 55 92 63 189 88 143 79 95 ...2 d2 X/ i; z/ Q0 L7 [5 e
    ##  $ platelet: int  190 221 151 183 NA 373 251 302 258 71 ...
    1 {1 E/ L9 o1 N: {, u  T##  $ protime : num  12.2 10.6 12 10.3 11 11 11 11.5 12 13.6 ...
    3 u; Y; \9 ^+ p5 I( i6 @( b##  $ stage   : int  4 3 4 4 3 3 2 4 4 4 ..., m5 E+ b8 F! S+ [! I7 a- S; h
    , A( O3 V4 V6 W+ f' ?5 S5 Q$ W2 `
    18 X( _' D3 X* @9 }4 H
    dim(dat) # 232 20; H+ M% \& ?! \: l
    1+ @/ E5 }9 x7 j& O% E, @8 e
    ## [1] 232  20
    7 A/ y8 W; g6 T2 a2 Q1
    & L9 z1 W9 @  L( O# A然后就是准备计算NRI所需要的各个参数。
    ( L1 s/ ?4 ~4 j( r7 x# V" K
    % U) `2 A2 q) _$ G8 e# W9 w# 定义结局事件,0是存活,1是死亡" V/ H7 f* N) ~( ?2 |
    event = ifelse(dat$time < 2000 & dat$status == 2, 1, 0)
    . v' b. o* y% Q& [2 @
    + G5 H( d( b4 u. d% y& V& O0 q# 两个只由预测变量组成的矩阵
    ' @% g7 Y& V! ^, K* M9 G4 Yz.std = as.matrix(subset(dat, select = c(age, bili, albumin))). C- f; i+ a% v/ c# ~
    z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime))); x( ^+ ?9 S! H: B
    # g  U3 d, Q$ T6 H( ~3 G7 B
    # 建立2个模型/ U; ^! f+ |- B( ?+ \) g, W8 S
    mstd = glm(event ~ age + bili + albumin, family = binomial(), data = dat, x=TRUE)5 X; q# {' i: X; J# {5 v) o% m
    mnew = glm(event ~ age + bili + albumin + protime, family = binomial(), data = dat, x=TRUE)( a0 U; e& f) t% R7 m1 P( Z+ ~
    " D. c1 b- a6 E! }4 R
    # 取出模型预测概率
    3 P3 d7 F9 x( D: p8 {p.std = mstd$fitted.values
    + o/ w5 w. a+ yp.new = mnew$fitted.values6 @9 @: b$ ~9 M' i5 l

    8 Y, U, t/ j2 P, D& _, f  `1
    2 Z1 F; C+ E+ Q' t. U5 x然后就是计算NRI,对于二分类变量,使用nribin()函数,这个函数提供了3种参数使用组合,任选一种都可以计算出来(结果一样),以下3组参数任选1组即可。 mdl.std, mdl.new 或者 event, z.std, z.new 或者 event, p.std, p.new。
    0 ~3 P- K+ N' {, q( |+ s, h1 h7 \) G
    # 这3种方法算出来都是一样的结果
    ' A- q1 }+ S! M9 c& W  \5 @$ i
      e& ~3 `( L- J1 [$ z4 g# 两个模型
    3 i! F3 f6 r* j1 F9 q% @. ]nribin(mdl.std = mstd, mdl.new = mnew, + e+ C- H  i' e
           cut = c(0.3,0.7),
    4 e8 ]' @/ h# T1 `  ]2 v       niter = 500,
    5 I" }, F. J+ a+ g       updown = 'category')# h, ?# x8 j/ k. W! p" d8 M9 o
    + L! ^9 R0 `, V: w
    # 结果变量 + 两个只有预测变量的矩阵
    5 V7 y3 G6 |$ |* N$ X. B: Lnribin(event = event, z.std = z.std, z.new = z.new, 9 _0 @: ?2 S* E
           cut = c(0.3,0.7),
    - @$ Z7 k" s( ?6 {5 K' h& ^       niter = 500,
    ) w; @4 d0 u5 _. [1 o       updown = 'category')
    + P# Z! m. o9 D9 h
    ' H6 i( p4 E9 S1 e4 j7 X: D6 e## 结果变量 + 两个模型得到的预测概率
    9 d) U  u9 f; L: pnribin(event = event, p.std = p.std, p.new = p.new,
    6 u2 Q' |6 n- \' T+ p4 _7 x       cut = c(0.3,0.7), 3 m1 o+ O9 n. N2 t7 a0 w& `
           niter = 500, . ^/ Q/ c/ |" h  S
           updown = 'category'); c8 }* Z# U' f& w1 W5 T

    # B# j/ f. C- {# b2 |) S2 m1
    7 E) V" @; T* Y: s其中,cut是判断风险高低的阈值,我们使用了0.3,0.7,代表0-0.3是低风险,0.3-0.7是中风险,0.7-1是高风险,这个阈值是自己设置的,大家根据经验或者文献设置即可。6 _' L$ i& g9 n, ?2 E
    6 ~1 t8 g/ V- v2 I$ t
    niter是使用bootstrap法进行重抽样的次数,默认是1000,大家可以自己设置。4 T1 n: N, W' X: H1 ~" ?- P: N5 P
    2 `$ t! c1 B; w  \# n8 \4 |/ s
    updown参数,当设置为category时,表示低、中、高风险这种方式;当设置为diff时,此时cut的取值只能设置1个,比如设置0.2,即表示当新模型预测的风险和旧模型相差20%时,认为是重新分类。
    9 F0 a: L  a! u) d: J" n
    , N- G! u- l8 I) J9 k: x5 Z上面的代码运行后结果是这样的:
    5 K4 x" d" S& m  s* t# [
    $ F' p! }( P: x" ^: f& qUP and DOWN calculation:  s/ ]3 c3 c! O3 S
      #of total, case, and control subjects at t0:  232 88 144
    7 A/ V% k0 Y- W9 Y' d2 i& W6 ~9 e( j
      Reclassification Table for all subjects:7 Z5 V9 f8 T3 n7 ]8 q
            New
    9 @6 K( n4 S6 j+ gStandard < 0.3 < 0.7 >= 0.7
    9 y# _) X2 S' M) ^8 Y  < 0.3    135     4      0
    + q$ |9 k/ J" t1 w2 G9 o, m  < 0.7      1    31      4% U4 ~( [- T) r6 m9 U2 V
      >= 0.7     0     2     55
    + q; g% n& {4 \3 m  ?
    . \& y9 o+ [9 {* c0 Q  Reclassification Table for case:
    7 I; G  P' k: q. U6 |        New; f6 S$ Y3 N$ J. r* f6 ?4 o
    Standard < 0.3 < 0.7 >= 0.7& z" B& R2 g* N( V4 D
      < 0.3     14     0      0
      T6 x% C/ W/ B, W! G+ U! ?  < 0.7      0    18      3$ c, `5 L) j* _8 t3 t) l
      >= 0.7     0     1     527 @4 Z( O- u3 U  d* q0 k
    * g, c. k3 u1 u( E5 S
      Reclassification Table for control:# N( p0 \& c+ E
            New
    ! h/ S5 X+ T% w1 c$ |2 \3 C# gStandard < 0.3 < 0.7 >= 0.7+ W3 ?: H1 k4 E5 R4 g$ |
      < 0.3    121     4      0
    & m5 n9 v) _8 }  < 0.7      1    13      1  v+ g# ]  c( E% R* p
      >= 0.7     0     1      3
    , I  H& X- H- E" K  K. U- r* `6 B0 y% a# p- O
    NRI estimation:7 ]% }- p, M4 y; t/ x
    Point estimates:
    ( c) G! B" G- b                  Estimate5 k- b- Y) X8 W: ]# S+ I1 _$ _- {
    NRI            0.001893939
    ! i  W+ r2 C2 L" g! T$ fNRI+           0.022727273/ R0 l: F; }0 F( X3 J0 Z. J. @* w
    NRI-          -0.020833333: I  f$ w/ s  M7 C3 L
    Pr(Up|Case)    0.0340909092 a% L8 d  \9 r' t/ {1 C7 J
    Pr(Down|Case)  0.011363636: ~: Q7 F. M7 ]! _' ~0 R% K
    Pr(Down|Ctrl)  0.013888889
    . o: U  ~. ^/ C  i! H2 O! N& xPr(Up|Ctrl)    0.034722222# v* t1 o- }3 @2 [9 N  g
    / L4 W) z1 h* N5 U* R! x( A
    Now in bootstrap..; @! K4 K) h; P2 [! ]& o2 T; J
    " s6 V+ `' q- P9 w4 Z
    Point & Interval estimates:0 h8 U. A! ~' L  l; ^3 d6 f& J
                      Estimate   Std.Error        Lower       Upper( n1 q* j4 e8 L/ b+ R1 P
    NRI            0.001893939 0.027816095 -0.053995513 0.055354449
    3 |0 L5 G1 Q* w. g+ aNRI+           0.022727273 0.021564394 -0.019801980 0.065789474+ K7 O: z  x$ E7 l: y  F2 E# [
    NRI-          -0.020833333 0.017312438 -0.058823529 0.007518797
      |2 U& P2 t7 t' o* z8 y$ \Pr(Up|Case)    0.034090909 0.019007629  0.000000000 0.072164948
    ! I  n5 ]3 b! r# Y: _Pr(Down|Case)  0.011363636 0.010924271  0.000000000 0.039603960
    6 ~& \* |: [8 ?* O* ^8 ^9 `/ V' CPr(Down|Ctrl)  0.013888889 0.009334685  0.000000000 0.035211268
    & K3 k' M8 H3 E7 cPr(Up|Ctrl)    0.034722222 0.014716046  0.006993007 0.066176471  k8 k+ s1 f4 M' t2 s( q

    " m7 z, |2 z. E/ L0 X0 p1 m% n1
    2 U: m* _0 @( U" I5 Z首先是3个混淆矩阵,第一个是全体的,第2个是case(结局为1)组的,第3个是control(结局为2)组的,有了这3个矩阵,我们可以自己计算净重分类指数。6 A( b2 S7 b6 K) Y% _8 y2 F

    9 O/ ~' `, b5 |; j4 x" S看case组:
    % O/ `$ Q& i! \. G* _4 Y# }  X5 _. E) D: u! E* |! E
    净重分类指数 = ((0+3)-(0+1)) / 88 ≈ 0.0227272733 h# B4 d2 k8 g2 v2 T; ?

    # ?1 [  h5 ^0 s9 u6 k再看control组:
    $ G9 S! L- L# X2 t" D* {) Z' h& Y# \, T0 m% `* s% M6 C; o
    净重分类指数 = ((1+1)-(4+1)) / 144 ≈ -0.020833333
    6 e5 _0 n1 }* j% S0 x5 ~" B
    + y) P8 q1 T1 S$ E0 w相加净重分类指数 = case组净重分类指数 + control组净重分类指数 = 2/88 - 3/144 ≈ 0.000315657
    ' Z" ?3 J4 h2 I) `" s* m- o9 Y- @
    ' p) a+ e% D6 c1 ~4 {! ]3 [9 g. o$ N7 s再往下是不做bootstrap时得到的估计值,其中NRI就是绝对净重分类指数,NRI+是case组的净重分类指数,NRI-是control组的净重分类指数(和我们计算的一样哦),最后是做了500次bootstrap后得到的估计值,并且有标准误和可信区间。0 d2 [$ S# i& {9 o+ |
    ! B# |+ @+ I% m) X$ r. q3 q( K
    最后还会得到一张图:
    2 ?9 K# Q3 w% X0 g. x9 d5 u# ?' V. r9 J
    这张图中的虚线对应的坐标,就是我们在cut中设置的阈值,这张图对应的是上面结果中的第一个混淆矩阵,反应的是总体的情况,case是结果为1的组,也就是发生结局的组,control是结果为0的组,也就是未发生结局的组。$ B# m, Q& X) D' n- n1 \  n
    ! T0 @3 ?$ A6 _% F$ d; P- \
    P值没有直接给出,但是可以自己计算。3 K7 @9 f: a" ]# W3 d' m3 Q4 ]
    7 R1 N1 j2 z0 Q3 y7 L. P) t/ H3 Q
    # 计算P值
    ! U# k! o9 v2 ]' \  Mz <- abs(0.001893939/0.027816095)4 [: j& h# O3 P% G( |/ E) ^1 O6 t
    p <- (1 - pnorm(z))*26 q0 }# R: N9 L# }+ h$ G/ _
    p
    2 L0 q/ y, t7 j/ x0 j8 H10 Y2 }( p/ N) ^% M
    ## [1] 0.9457157
    # `# x! ]) V" [. `- X0 `9 g1* q" e/ w+ f, ]  e0 c: ~: o
    PredictABEL包
    : m  }$ _2 M' w! ^. V0 s; h# C' W5 r#install.packages("PredictABEL") #安装R包
    ( u3 ~2 ~7 q. _! P3 j  |. E) Olibrary(PredictABEL)  
    % ]8 Y) `, T. ?( E& A2 M
    ; z8 v( _" E* z% L/ ]5 l# 取出模型预测概率,这个包只能用预测概率计算
    ( y  W5 w, }3 N& r0 v: rp.std = mstd$fitted.values$ {* y- D! k% E4 ^9 f  U
    p.new = mnew$fitted.values
    ; @1 x' K0 Y# v+ ]7 j) }14 O( }0 s( r( V% @4 |* N) u; r0 [
    然后就是计算NRI:
    : S6 I% c; u0 _  d0 G9 v
    " d* {) }3 G1 a8 t" X# z$ y6 tdat$event <- event
    ' U$ i" M5 g0 p9 Q" p3 h
    , V4 R' j* h* Z, v( w. ]# k/ [: ~; Sreclassification(data = dat,
    8 S% e. Q0 Z7 X' |% k+ ?! L# [; V                 cOutcome = 21, # 结果变量在哪一列
    8 O1 c  v5 b& `- R  E! i( H% P  H                 predrisk1 = p.std,& T. T( P" o2 b0 Y
                     predrisk2 = p.new,& Q+ V% |3 k% F% _9 E
                     cutoff = c(0,0.3,0.7,1)
    0 w" d- y3 R. y6 M1 l                 )" ?, v1 L0 |0 j( {5 X# Q2 e" ]
    1
    6 [9 D9 j) H$ ?# ~0 ^$ w9 ?4 p##  _________________________________________  K5 j. F, ^0 v6 V
    ##  
    3 v3 x  e# v) g% y9 {& N8 D* r1 Z##      Reclassification table   
    ( B/ ?- g& C, ~! c; n8 _$ M##  _________________________________________
    3 k% `; l$ Q% l. [2 E/ C##
    . |, p, o3 l3 ?* m##  Outcome: absent
    + ]$ \; Q7 M  ^# [##   
    $ H% y3 T& _9 ^& ?# [##              Updated Model
    9 ?9 _' b( K: y- w: j## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified
    ) Z5 D4 X2 v6 d4 u# T6 O! |2 A6 e##     [0,0.3)       121         4       0               3
    . j/ @+ m' x! g" M- s" G% T7 I##     [0.3,0.7)       1        13       1              13# _3 Z1 A$ h- k# C, p
    ##     [0.7,1]         0         1       3              259 j) u/ t- }( |- G
    ##
      W6 G7 w1 _) v* O##  
    ' ]8 b) e3 v6 P0 x3 l$ t" v##  Outcome: present 6 Q! Q- x2 o, P+ h* [8 f
    ##   
    ; j5 C' G0 b- I5 p" I- R##              Updated Model
    7 A5 A! u& U% {) ~6 y! o## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified
    % R$ H! q. Q+ v4 g##     [0,0.3)        14         0       0               0- w7 ^) d4 \& _% @% g. U6 [5 T
    ##     [0.3,0.7)       0        18       3              14
    ( x, b3 i7 j& N+ }9 Z##     [0.7,1]         0         1      52               20 t: o6 \4 Q0 N( r/ s
    ## ( D4 i! e6 \9 i/ D; @% D
    ##  + {5 J. U# b! v* U
    ##  Combined Data
    % a5 o  E3 k' o4 Q' I##   
    & Z+ o9 p0 ]6 E" o/ _, s4 z##              Updated Model) {- P! G, k$ P0 V$ K4 w) f; b# F
    ## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified
    . F4 J. F1 ~- i( d1 w3 [##     [0,0.3)       135         4       0               3( x3 z0 |  g& X
    ##     [0.3,0.7)       1        31       4              14" n; z+ S0 L& j8 |7 ~* @" S
    ##     [0.7,1]         0         2      55               49 ~( D( A2 \, q' `
    ##  _________________________________________
    + x, |7 ?4 B. p" n## - |% L2 w% f3 M9 _' w9 q' }
    ##  NRI(Categorical) [95% CI]: 0.0019 [ -0.0551 - 0.0589 ] ; p-value: 0.94806 # g7 |, y4 I9 V* R' o- I6 T
    ##  NRI(Continuous) [95% CI]: 0.0391 [ -0.2238 - 0.3021 ] ; p-value: 0.77048
    ) |( |; K  `% O) j1 n##  IDI [95% CI]: 0.0044 [ -0.0037 - 0.0126 ] ; p-value: 0.28396
    4 n3 Y! z0 q% ?4 r& z) W' |* [; Z" m3 J; D, P
    1
    0 _" `, T% |9 z* P9 c结果得到的是相加净重分类指数,还给出了IDI和P值。两个包算是各有优劣吧,大家可以自由选择。0 {5 i$ x) j  d) |2 G( ^* r& e- V6 w' O

    , _& {+ n+ d8 r; l4 B: o生存分析的NRI
    ( e3 Y+ |- C6 H. F还是使用survival包中的pbc数据集用于演示,这次要构建cox回归模型,因此我们要使用time这一列了。$ l* w& L* w  F2 S9 N9 ]* T
    * p: _, v7 ~' {( B4 b
    nricens包( t4 ?; b/ i7 a6 v" R4 J2 h2 ?
    library(nricens)
    , }9 L( A0 K! u( D5 qlibrary(survival)1 j0 n, l# N" R0 s9 `- ]
    5 C6 F3 w) |# j7 {6 f- l
    dat <- pbc[1:312,]5 D9 m8 R5 D, ^3 v
    dat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡  r2 ?: h7 H; `
    1
    3 W9 w  `; S* w; {+ e然后准备所需参数:( z3 T& P5 N3 w$ j3 i3 F( m

    # H8 o& F8 G) B9 k, P" a# 两个只由预测变量组成的矩阵
      d! }7 j: V, X" rz.std = as.matrix(subset(dat, select = c(age, bili, albumin)))0 T2 v8 a# u2 p, w
    z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime)))
    ' k& r$ s/ G5 E; ~
    0 f# z2 e" h: s; k% q/ H! t$ \# 建立2个cox模型9 |1 H" l, n, D# F3 B- N4 T
    mstd <- coxph(Surv(time,status) ~ age + bili + albumin, data = dat, x=TRUE)4 ^* o0 K$ ~) t0 c3 s0 k( v* M: w
    mnew <- coxph(Surv(time,status) ~ age + bili + albumin + protime, data = dat, x=TRUE)+ u9 X1 Y7 e$ d# T3 l2 p# |1 C7 s
    - M# ^7 p' I+ g
    # 计算在2000天的模型预测概率,这一步不要也行,看你使用哪些参数! \% z/ }8 B7 @5 ?
    p.std <- get.risk.coxph(mstd, t0=2000)
    6 I+ V* n; Z  O, p) s- x- n2 z3 v: lp.new <- get.risk.coxph(mnew, t0=2000)! T3 l3 j+ r" n; G
    1% i8 _1 J) Z5 `: b/ K) C
    计算NRI:
    5 J) E; w8 U1 Y: W4 S5 |
    $ G; m7 q4 g6 X) j2 qnricens(mdl.std= mstd, mdl.new = mnew,
    1 r& T$ [- W* B6 L- t        t0 = 2000,
      A. z$ ?/ a4 [! r" w        cut = c(0.3, 0.7),
    , q3 n7 Q, a, b% a1 |        niter = 1000, + p/ }$ E4 U, ^( C, U  i
            updown = 'category'): F: l+ F" p  ^
    " [- d" q* T4 D- t" o3 t" X& ~
    UP and DOWN calculation:
    ) A( B0 ^3 |( K+ `5 u4 K) X" S# e- o  #of total, case, and control subjects at t0:  312 88 144
    + h6 j) r# {' b# b( Z7 V5 {; p% u2 Q8 G- B/ S1 w7 ?
      Reclassification Table for all subjects:
    7 L5 I0 c( {. I4 W: J+ ?        New
    0 j" a$ o+ \9 N  y: NStandard < 0.3 < 0.7 >= 0.7. I1 K' j, W, k
      < 0.3    202     7      0: h3 ~3 t9 Q/ w& ~' ]6 A9 E4 h% w
      < 0.7     13    53      68 R3 W/ Y$ S9 U  O( K. j9 Y3 @3 E
      >= 0.7     0     0     31
    / }: U/ ]) b. @9 p; n$ M$ c( J. _8 ]. O
      Reclassification Table for case:4 y  _6 a1 J( ]3 _
            New; i* F9 T  R. }; R- J( C, Q+ F$ z
    Standard < 0.3 < 0.7 >= 0.7
    $ ?( h) A4 [6 U9 D7 f9 \  < 0.3     19     3      0
    * }3 A* J2 ]4 g' F- Q4 @/ ?  < 0.7      3    32      4( }' `1 D1 l* u( X# }5 r& F+ G
      >= 0.7     0     0     277 A1 A% z1 |# x! o* C

    # e2 S" S1 V2 \4 I& Z9 y! y2 Y+ J" r  Reclassification Table for control:
    % ~/ K4 ~3 K. {1 ]6 M/ W5 o        New
    5 [+ n$ z: e3 h$ YStandard < 0.3 < 0.7 >= 0.7
    ( H7 X- X% w! ^3 C; R  < 0.3    126     3      09 p0 F! `  B  V0 [! @# }
      < 0.7      5     7      2
    " @4 a/ u; Y$ w; i* u8 b  >= 0.7     0     0      1
    * p3 ]" R: C( D/ H" ?2 p0 B  s8 w' }+ r( \6 K$ _3 `
    NRI estimation by KM estimator:6 y6 F& D' z* Y' s4 r0 c) M

    6 `" m/ `* B0 x# z! V( h) K; LPoint estimates:0 Y- H6 Y7 J7 z$ p9 F
                    Estimate) b& g, z6 F1 A: I& P
    NRI           0.05377635+ c9 n6 o2 |2 d+ D. ?% c
    NRI+          0.03748660
    + ?! ^. [9 L; n& ?% i' w( ~NRI-          0.016289745 o8 c7 K3 T: h3 o
    Pr(Up|Case)   0.07708938
    3 A, n4 A7 S# I, [. f7 L" bPr(Down|Case) 0.039602781 K$ [$ h, F% }9 F0 g* {
    Pr(Down|Ctrl) 0.04256352
    , ]) v7 F6 L  b3 F2 e; LPr(Up|Ctrl)   0.02627378
    / c' K1 h: h  {  E: b5 t: z" q
    ( q2 N6 \( F, c* U/ k2 j# UNow in bootstrap..
    $ `. Z2 I$ ?6 X& p* ]8 @
    ; S3 n9 a3 ^# J$ ], K4 MPoint & Interval estimates:
    # t0 }6 ^7 D& }$ j7 v5 v                Estimate        Lower      Upper! J" I2 [3 z  I, ^* U
    NRI           0.05377635 -0.082230381 0.16058172
    , P0 T5 x/ ^2 U0 {! J- G1 CNRI+          0.03748660 -0.084245197 0.132317768 R3 _. c: h6 Q/ w% C  v6 y$ h
    NRI-          0.01628974 -0.030861213 0.06753616
    5 {& t- l! @) R6 pPr(Up|Case)   0.07708938  0.000000000 0.19102291
    ; U  H0 ~! k3 T4 {; a! O) PPr(Down|Case) 0.03960278  0.000000000 0.152360166 l" y/ u/ O9 u) n( o1 x
    Pr(Down|Ctrl) 0.04256352  0.004671535 0.098631705 Q$ X) \7 s) t. F/ Q" {9 [; t$ S- `
    Pr(Up|Ctrl)   0.02627378  0.006400463 0.05998424
    + M0 ]% P6 ]( a  v" k, x. F" o9 h7 L9 {# l: V/ y0 P. K
    1" e0 K7 v4 ]% j, q" I3 s
    & `, Q4 e, a; {8 @3 Q" m, K
    Snipaste_2022-05-20_21-49-386 d! V" D( a, o9 t* O
    结果的解读和logistic的一模一样。
    $ V( E1 @4 z% C- V( B4 X' l  L  m# u- L2 \( K9 f. W  P
    survNRI包
    1 e( k; {5 x2 M4 d- C( ~, t1 f# 安装R包& |+ \  `- T! E% }
    devtools::install_github("mdbrown/survNRI")9 s0 {2 `$ k+ i9 i+ u# p0 ~* z
    1
    - ~$ L5 D" r. t3 u5 f  B& b加载R包并使用,还是用上面的pbc数据集。5 e- g) O9 N, E
    : C3 D: P( U5 j. E. e
    library(survNRI)( a; P! Y2 H2 {
    15 I0 e6 v3 R" F% K9 Z
    ## Loading required package: MASS
    0 l6 R0 u4 _* G1# V; x& r7 u) }; v. B
    library(survival)$ @$ C4 G) A& Y$ y
    + \( r; d2 o* D8 s
    # 使用部分数据- Q0 {: K0 h" A" l7 n
    dat <- pbc[1:312,]
    " I% L. q1 a8 g. t7 Qdat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡
    * g, B0 b4 k7 }: q0 g$ j4 j  l7 b% }1 a; Q
    res <- survNRI(time  = "time", event = "status", - ~2 S) t% l! ?" i- \" m
            model1 = c("age", "bili", "albumin"), # 模型1的自变量5 M7 u: L& b5 r# K7 l
            model2 = c("age", "bili", "albumin", "protime"), # 模型2的自变量5 ~3 l$ c- a0 l3 J  k$ k# }
            data = dat,
    8 p# u0 f3 w, ?& W0 s- V' I+ @5 `        predict.time = 2000, # 预测的时间点
    $ ]7 N! s% ]7 ~* a1 p$ y; w# Z. s1 p        method = "all",
    8 u5 V/ |: ~% G' T% @# B        bootMethod = "normal",  * Y, w/ q7 L& n0 n) ]- z2 k4 S
            bootstraps = 500, : X. _+ G7 `9 s" z
            alpha = .05)
    1 ?2 ~* K2 l: W; }
    5 w! Y& Y  E& @: {8 _! F+ g1- D$ a9 g) X: K2 O, U! ~3 |: R
    查看结果,$estimates给出了不同组的NRI以及总的NRI,包括了使用不同方法(KM/IPW/SmoothIPW/SEM/Combined)得到的结果;$CI给出了可信区间。; c& I. {6 ~9 R

    ! |1 Z3 M, g; T  f( w- `res
    % S. a& n' V' t% n. R2 @- F1
    : X9 i) W% p/ c. U5 w## $estimates/ v' k. C5 _0 w. M- M
    ##            NRI.event NRI.nonevent       NRI
    / J/ K4 R+ a7 X9 O. g( G## KM        0.20445422    0.3187408 0.5231951% Y) x/ R2 w' i! t7 a# b+ U
    ## IPW       0.22424434    0.3273544 0.5515987$ b3 G& M0 _; n9 X6 f
    ## SmoothIPW 0.19645006    0.3144263 0.5108763
    ' R: x- Y  ]" y& ?: a## SEM       0.07478611    0.2632127 0.3379988/ E+ a" C1 T) n9 L, i
    ## Combined  0.19633867    0.3143794 0.5107181# u; X2 C2 V( u: Z
    ##
    ) j! \: n  C3 Z% b## $CI
    / N* H+ X: i' b8 x% J## $CI$NRI.event
    ' L5 ?2 d/ Y' w2 a& w5 M+ [& l##                     KM         IPW   SmoothIPW        SEM   Combined
    4 G( [5 s' o# q1 r% r## lowerbound -0.03915924 -0.02185068 -0.04724202 -0.1162587 -0.0473723
    . X8 @9 N  t3 q2 U& C## upperbound  0.44806768  0.47033936  0.44014214  0.2658309  0.4400496
    ' j/ N  D. h. \$ S## $ q4 L- w' b- m
    ## $CI$NRI.nonevent
    , e8 s' E4 w7 h( X( v  U& D0 X" f##                   KM       IPW SmoothIPW        SEM  Combined' G7 f0 Z1 p6 C2 ~" O# U
    ## lowerbound 0.1317108 0.1396315 0.1286685 0.08638933 0.1286426
    ! r+ N7 M+ n+ k! \% L, e## upperbound 0.7102251 0.7393216 0.6966341 0.51482212 0.6964549
    ' v% ~2 K& @% b6 I1 ?8 [## 1 W8 S3 U) B; r# X; b+ p* [
    ## $CI$NRI+ Q2 r4 n2 \1 g9 U& f$ q0 b# d& I
    ##                     KM         IPW   SmoothIPW         SEM    Combined
    4 L# I& A* B1 |% R. H0 u* g6 u( r# N## lowerbound -0.05112533 -0.04569046 -0.05439863 -0.04132364 -0.05443409! F, p& H6 I% M# s
    ## upperbound  0.89306122  0.92464359  0.87970125  0.64253510  0.879531534 i8 i6 W! M9 Q& ~
    ##
    " E$ Y; {; `/ I% O# S3 g4 d## # O" n9 w: w+ C2 @2 z7 G
    ## $bootMethod
    2 ^; x8 v6 B; t8 o2 |# v; l# G## [1] "normal"
    9 e0 q% A' S  J" f# e& Q##
    / L! o2 J) J5 J% i7 [  A) G/ X## $predict.time& K+ M4 u1 A$ Z1 s* V
    ## [1] 2000# U- L( b* B% \& }% k1 I
    ##
    , M1 \/ ~* a  p. W: _. \, o9 u- G, R## $alpha
    ) a( y6 S& m" K! u% _; ?$ S5 p## [1] 0.05( }3 D4 l, c' R) o# j4 v. A
    ## % f$ ]4 S& a' ]* J: L' W
    ## attr(,"class")( W/ j1 U6 d/ i& a' k8 M) L
    ## [1] "survNRI"
    8 Y3 x( _# t$ w2 \" O1 D' H1 S$ w3 p& \" B. L7 m$ X. Y
    19 G+ S. v& L, h( B) @0 x9 e, g7 }
    OK,这就是NRI的计算,除此之外,随机森林、决策树、lasso回归、SVM等,这些模型,都是可以计算的NRI的,后面会继续介绍。大家如果有问题欢迎在评论区留言。+ R0 z4 C: B2 X8 G$ |! B) j' f
    ' ^. K) I. e& [" K* r9 R; J! b
    本文首发于公众号:医学和生信笔记
    6 `8 r1 v4 {& y; s
    4 T5 l6 N) Y# p: X; e0 J" b“ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。
    / i! `9 w, E/ v; C1 R本文由 mdnice 多平台发布
    ! z0 ^& y# K7 _  Y————————————————
    0 L5 g* K9 {/ ]) V* S# Q版权声明:本文为CSDN博主「阿越就是我」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    . \# T0 U0 ?) a原文链接:https://blog.csdn.net/Ayue0616/article/details/1267680064 q* U! z  C3 v, l# A
    # ?$ B. I6 w7 U( M+ H& h2 e; U- x
    0 Y. R0 v7 a* o: i! O
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-5-25 10:41 , Processed in 0.434594 second(s), 51 queries .

    回顶部