QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3028|回复: 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
    % Z- C& G8 n% l) p
    净重新分类指数NRI的计算" T* T7 Q7 v4 \) m( ?
    “ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。4 k; m- d4 [$ u- O
    NRI,net reclassification index,净重新分类指数,是用来比较模型准确度的,这个概念有点难理解,但是非常重要,在临床研究中非常常见,是评价模型的一大利器!: F, O0 K, _# G( V& Z1 |$ }% }
      O: T( ]( w. u& P& \. L5 m3 U
    在R语言中有很多包可以计算NRI,但是能同时计算logistic回归和cox回归的只有nricens包,PredictABEL可以计算logistic模型的净重分类指数,survNRI可以计算cox模型的净重分类指数。
      A! d6 y: v3 F& s0 e9 m4 v5 |/ ~9 f3 Z2 N+ G) }
    logistic的NRI' {7 g3 |7 O( q4 \! l" \+ L) Q
    nricens包
    # O! v! W4 J/ ePredictABEL包/ J3 X3 Q1 C* d* Y' F
    生存分析的NRI# I4 `4 K3 ^: r# T$ O7 [; A) ^
    nricens包
    ( G7 ^, V* _, M/ O  J# `7 F( ]survNRI包
    : E$ N( D: F: @9 zlogistic的NRI
    1 X$ L, `1 @8 k* H" E, W( F: Knricens包
    ; {4 V1 r. r5 {0 @% f( m#install.packages("nricens") # 安装R包/ L' A& P% Q0 q4 k, U0 P
    library(nricens)
    ) F$ J$ P! [, ?6 ~1, E: g' I6 r: D& W# h
    ## Loading required package: survival
    , X% [/ b& _& b- q19 H6 [7 {; ?5 y# s
    使用survival包中的pbc数据集用于演示,这是一份关于原发性硬化性胆管炎的数据,其实是一份用于生存分析的数据,是有时间变量的,但是这里我们用于演示logistic回归,只要不使用time这一列就可以了。
    4 l: e- ?$ M9 |7 y7 Q" G2 t& o; W& m% C' R. Z8 b, K
    library(survival)
    9 `4 E1 ?( m3 N( n; o% R" G( o- a& A0 h0 e6 ]
    # 只使用部分数据( K, J+ T9 u! j+ R/ S6 Z
    dat = pbc[1:312,] ( b! _. R. r4 J* t, l
    dat = dat[ dat$time > 2000 | (dat$time < 2000 & dat$status == 2), ]( }7 \0 P" o. [
      q; u# R7 D1 J5 Q9 \' c
    str(dat) # 数据长这样
    . K+ G  _# u) p' F" v1
    2 g2 K6 s3 s8 C## 'data.frame': 232 obs. of  20 variables:
    9 f# ~& f5 h+ @##  $ id      : int  1 2 3 4 6 8 9 10 11 12 ..., l8 g/ d. i+ {7 l) @7 X8 v
    ##  $ time    : int  400 4500 1012 1925 2503 2466 2400 51 3762 304 ...( `1 a( u6 q" n7 p! O( T. }* t. e
    ##  $ status  : int  2 0 2 2 2 2 2 2 2 2 ...! ?' @# ]4 @7 m7 Z0 T0 Y0 z
    ##  $ trt     : int  1 1 1 1 2 2 1 2 2 2 ...
    ; v0 j1 |1 Y# P. E1 j; ]# k4 C2 t##  $ age     : num  58.8 56.4 70.1 54.7 66.3 ...% W7 L7 K7 M, x
    ##  $ sex     : Factor w/ 2 levels "m","f": 2 2 1 2 2 2 2 2 2 2 ...( R, O; f0 [. y: t5 w
    ##  $ ascites : int  1 0 0 0 0 0 0 1 0 0 ...
    5 [& f' Y+ {; }' o##  $ hepato  : int  1 1 0 1 1 0 0 0 1 0 ...5 L. U- m$ U0 I: i8 w7 k
    ##  $ spiders : int  1 1 0 1 0 0 1 1 1 1 ...
    3 v4 ^$ J2 o* ?3 L; K##  $ edema   : num  1 0 0.5 0.5 0 0 0 1 0 0 ...2 E! B" {, c& C  n
    ##  $ bili    : num  14.5 1.1 1.4 1.8 0.8 0.3 3.2 12.6 1.4 3.6 ...& E; Q# J5 ?, i. |. z3 q' E
    ##  $ chol    : int  261 302 176 244 248 280 562 200 259 236 ...
    , @" }; c% {. e) {9 c2 g##  $ albumin : num  2.6 4.14 3.48 2.54 3.98 4 3.08 2.74 4.16 3.52 ...# ^* L& [5 L& O) I2 _
    ##  $ copper  : int  156 54 210 64 50 52 79 140 46 94 ...9 H7 z, K" `9 m: L( c2 j
    ##  $ alk.phos: num  1718 7395 516 6122 944 ...
    % W0 f6 C  e8 h' M" u##  $ ast     : num  137.9 113.5 96.1 60.6 93 ...# t7 U6 M6 R! }! M0 w
    ##  $ trig    : int  172 88 55 92 63 189 88 143 79 95 ...1 u" B$ b% ?' f9 B6 o% g+ R0 }
    ##  $ platelet: int  190 221 151 183 NA 373 251 302 258 71 ...
    + j4 M/ D) _$ A! e+ W4 w##  $ protime : num  12.2 10.6 12 10.3 11 11 11 11.5 12 13.6 ...
    ) k2 m* i* y, C6 \: r##  $ stage   : int  4 3 4 4 3 3 2 4 4 4 ...
    % R1 O! y2 s+ ]0 p2 d% t( q' w4 `2 ~
    19 A& o6 B% f  p0 V% |
    dim(dat) # 232 20+ B* ~' c+ t$ N, C) q
    1
    / u0 H1 _5 r3 M, s. L0 i## [1] 232  20% v) y: z+ S- T! D
    1
    ' l$ E9 Z$ W7 C  d. w( t然后就是准备计算NRI所需要的各个参数。' M& y# R+ ?% `$ P% }2 Y  ?
    * s* G2 U" Y: P5 Z7 [9 {" S
    # 定义结局事件,0是存活,1是死亡
    . M( f6 a/ x# e4 B' oevent = ifelse(dat$time < 2000 & dat$status == 2, 1, 0)- ?# S  X& z- K6 f7 F; z1 f* r' o

    9 ^- j2 K- f  c/ z% D2 Y# 两个只由预测变量组成的矩阵6 @( }6 ]$ a5 N* j( C# p2 e
    z.std = as.matrix(subset(dat, select = c(age, bili, albumin)))1 C. l0 h" Z9 M0 W
    z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime)))
    ! P; W9 u0 Z# M; m6 }# F3 b1 M" ?1 @$ r  o
    # 建立2个模型
    3 x" z: j! N) a- qmstd = glm(event ~ age + bili + albumin, family = binomial(), data = dat, x=TRUE)% M- r7 v# c* U" J  J% l
    mnew = glm(event ~ age + bili + albumin + protime, family = binomial(), data = dat, x=TRUE)
    7 b& z0 t3 ^# Y9 N  O. B8 m+ L; c, E5 D
    # 取出模型预测概率
    % _' O0 p& m# A% A! ^( Hp.std = mstd$fitted.values# s7 s- m! T* l* z9 Y) W1 K
    p.new = mnew$fitted.values( K; ?' q' s" f0 ^& v5 J

    ) b$ C* W8 |2 j% q1
    ' F- h  v/ W! m. i. C然后就是计算NRI,对于二分类变量,使用nribin()函数,这个函数提供了3种参数使用组合,任选一种都可以计算出来(结果一样),以下3组参数任选1组即可。 mdl.std, mdl.new 或者 event, z.std, z.new 或者 event, p.std, p.new。0 S) H" b  @& t4 g0 H) K9 J

    ' R& ]# w& S- l) g3 R) W# 这3种方法算出来都是一样的结果8 x" E3 A3 x$ ~

    8 I8 @) g, `; m' \  l# 两个模型4 q9 Q: P0 ?/ D6 a
    nribin(mdl.std = mstd, mdl.new = mnew, * O! }1 M9 z8 E4 X. `) x
           cut = c(0.3,0.7), ) T' v, `* q5 H$ K- g
           niter = 500, * `- @9 r2 z/ V7 T- f. S1 o
           updown = 'category')
      B/ j* m- p1 i! E1 N+ ~# r0 B, H' j
    # 结果变量 + 两个只有预测变量的矩阵
    ' u$ x7 A1 v- o  {% }$ rnribin(event = event, z.std = z.std, z.new = z.new, " w# U" k& K' u) ~+ R1 B- B
           cut = c(0.3,0.7),
    . G9 Q4 Z6 a4 C       niter = 500,
    + ?4 ^) J: ~1 c! v; P       updown = 'category')
      {" o3 |* c, l& D( U" M6 ^
    ( A$ c0 G% f& h) N6 c6 z5 J/ |# z## 结果变量 + 两个模型得到的预测概率4 q& m4 V% R! s2 f% Z
    nribin(event = event, p.std = p.std, p.new = p.new,
    / [& ]: y4 ]' N( [       cut = c(0.3,0.7), 7 k9 x& g( r7 J1 A
           niter = 500,
    8 V3 o4 W1 ]( N3 J4 ^3 G       updown = 'category'); T  ~. ]) w/ C- k& E. X/ i

    6 f& D# b" \+ X1
    3 @6 _. L7 G5 d, Q8 b其中,cut是判断风险高低的阈值,我们使用了0.3,0.7,代表0-0.3是低风险,0.3-0.7是中风险,0.7-1是高风险,这个阈值是自己设置的,大家根据经验或者文献设置即可。, k& [2 v: W/ \2 z( R& X
    ( m+ m! a: g" R  f
    niter是使用bootstrap法进行重抽样的次数,默认是1000,大家可以自己设置。% h& a5 @# r* k7 E# c6 R

    ( z& [6 k' Y6 K$ Z: k1 ?8 gupdown参数,当设置为category时,表示低、中、高风险这种方式;当设置为diff时,此时cut的取值只能设置1个,比如设置0.2,即表示当新模型预测的风险和旧模型相差20%时,认为是重新分类。3 Y0 H/ w7 H& K1 m& q
    : j# t# @) h1 W' s. S6 Y
    上面的代码运行后结果是这样的:
    - X% n! [: c3 Y! J" _) {/ j  i" l  ~- ~8 j% E4 E% L- S8 y0 r6 n
    UP and DOWN calculation:
    , l! B9 U: D. @6 @" t' |+ j  #of total, case, and control subjects at t0:  232 88 144
    # ?- M0 x' j$ H4 \" U4 W* `6 l8 D; ]' @& x. I, i5 \$ o/ I
      Reclassification Table for all subjects:
    # g3 J) h+ o, S7 R' d        New
      ^, X( [+ i: `& N4 |; |& a* pStandard < 0.3 < 0.7 >= 0.7
    ! c9 O9 s' T6 f3 }+ d/ R0 L  < 0.3    135     4      0  v# A" M; A2 g
      < 0.7      1    31      4
    * e$ D4 U3 q/ }2 {* s& r  >= 0.7     0     2     557 t; i6 A9 f( \' l2 f8 W: l
    ( c1 l- j5 j6 j! ]# D/ f: s
      Reclassification Table for case:
    8 T: j  u* n' b- K6 p+ r        New6 I' _# l* z0 u2 O8 \- ?
    Standard < 0.3 < 0.7 >= 0.74 |( r  ]  m" A8 z
      < 0.3     14     0      0+ ^" e( c, B; i. L0 t" `8 \
      < 0.7      0    18      3
    ! y5 J& x8 L9 |* e+ ~7 G% f$ `  >= 0.7     0     1     52# L1 r0 k/ O6 q  G$ f" x
    3 y* m/ T) O1 ^6 W, C/ a
      Reclassification Table for control:9 w* Y: Y4 q: c- x  W* ~# x1 M
            New# h6 G% a- [6 i8 K# R  N7 ~
    Standard < 0.3 < 0.7 >= 0.7
    % S6 m% [4 ^% l& R* h+ |8 M# t" ~6 u  < 0.3    121     4      0
    6 K+ n7 ~& Q/ J' H  < 0.7      1    13      1  I5 j! J0 W. H7 @7 A2 u
      >= 0.7     0     1      3
    4 E+ N  {! h6 s7 |, t6 |
    ) v" Z8 {' {2 p, m# p7 x7 \NRI estimation:7 ^! ~+ z% ]  K1 |3 O0 V7 _
    Point estimates:+ e# X& U9 y# O( r  {6 s
                      Estimate
    , e5 _8 h/ {2 i4 P- K& J* tNRI            0.001893939
    7 v2 O% F7 Z% K, N4 l/ ^  J8 pNRI+           0.0227272731 J3 G; a$ z5 G* O' H
    NRI-          -0.020833333
    ) T( _* I3 [5 ^Pr(Up|Case)    0.034090909
    / M- N" W: W1 j1 S* Q! |Pr(Down|Case)  0.011363636
      O5 j6 y! r5 w/ x: @* R0 IPr(Down|Ctrl)  0.013888889# Y+ H7 w3 Y' S  I$ t0 {7 K
    Pr(Up|Ctrl)    0.034722222/ h  u" ^- u; u( O0 i
    2 w. ~) g* h( ~9 b
    Now in bootstrap..
    % b; H0 T7 C+ l7 {; o6 p" a3 ^0 u5 c9 c4 ?" `. L2 {! M
    Point & Interval estimates:+ G  y: `% s( a: {+ F
                      Estimate   Std.Error        Lower       Upper! a6 T& R0 \6 R, y4 }$ ~3 i
    NRI            0.001893939 0.027816095 -0.053995513 0.055354449
    6 O. E4 u9 C* x3 }/ uNRI+           0.022727273 0.021564394 -0.019801980 0.065789474
    + ^  b# f" u' N/ yNRI-          -0.020833333 0.017312438 -0.058823529 0.007518797- G$ K& O4 h; }  ~# j2 V
    Pr(Up|Case)    0.034090909 0.019007629  0.000000000 0.072164948
    . x% u* F  j, Q3 K: B; @Pr(Down|Case)  0.011363636 0.010924271  0.000000000 0.039603960) @  w% v! E6 h' \# G# ]7 I6 \! t
    Pr(Down|Ctrl)  0.013888889 0.009334685  0.000000000 0.035211268: X- l( F2 B$ M+ X- T- e. o
    Pr(Up|Ctrl)    0.034722222 0.014716046  0.006993007 0.066176471
    0 \9 m& a1 t8 v0 M
    0 [0 l5 m4 U9 y0 O0 }% q9 {11 p3 Z0 F$ s+ G5 t2 D- T- e
    首先是3个混淆矩阵,第一个是全体的,第2个是case(结局为1)组的,第3个是control(结局为2)组的,有了这3个矩阵,我们可以自己计算净重分类指数。
    4 N! g3 K. P) j0 S- q- _7 K
    5 Z% ?7 U) H* O$ {% ?% b# W  W看case组:
    4 q: N2 q& v( n9 ]# b; F- [1 [; M* e
    净重分类指数 = ((0+3)-(0+1)) / 88 ≈ 0.022727273
    $ w3 q  V0 l7 @4 A$ N
    ( o0 a, R, g. }7 i  j再看control组:; V2 p! R1 D. F! Q4 x
    % B4 r7 r! }' I* J3 m1 J8 E  ^
    净重分类指数 = ((1+1)-(4+1)) / 144 ≈ -0.020833333- K, q( _) S* O* h

    9 l0 N% j1 |2 Q( S% x$ K相加净重分类指数 = case组净重分类指数 + control组净重分类指数 = 2/88 - 3/144 ≈ 0.000315657; H% d: b7 o! M3 ]3 J% K
    ; A- M. f# [2 u& \/ h- g7 I
    再往下是不做bootstrap时得到的估计值,其中NRI就是绝对净重分类指数,NRI+是case组的净重分类指数,NRI-是control组的净重分类指数(和我们计算的一样哦),最后是做了500次bootstrap后得到的估计值,并且有标准误和可信区间。
    % w# \# C" A5 ?" ^4 L
    # Y* D7 O. k) x0 M4 ~( P- u2 r最后还会得到一张图:- B" b/ t8 G5 b+ V
    ) s2 G- Y3 x9 k8 G% ~$ }) b8 _
    这张图中的虚线对应的坐标,就是我们在cut中设置的阈值,这张图对应的是上面结果中的第一个混淆矩阵,反应的是总体的情况,case是结果为1的组,也就是发生结局的组,control是结果为0的组,也就是未发生结局的组。. {, l( H8 k' `3 T/ {  o. v
    % T" V$ J+ ]+ t5 [0 m3 _3 h
    P值没有直接给出,但是可以自己计算。
    % Y  Z+ u6 J7 j5 C! l$ q, N, ~( }; p6 l/ x) B3 ]. _
    # 计算P值: b- T7 w* a, X7 W' {" V; D5 d
    z <- abs(0.001893939/0.027816095)
    4 K- z8 }  _+ m/ a. J0 j8 [p <- (1 - pnorm(z))*2
    ! O- V3 }$ v1 o5 q' l2 qp
    ; u. {& t9 }0 |19 D. U, e3 S0 N3 p$ D$ ^: H( {
    ## [1] 0.9457157
    , `: |5 P/ e5 z+ K& z16 E& f' L( i, h+ c3 s$ Z
    PredictABEL包
    8 _' `/ r0 w0 M/ e9 E+ p% j: q#install.packages("PredictABEL") #安装R包6 @" l5 `1 |! z/ O/ C+ }) q
    library(PredictABEL)  7 Y0 ?9 w. _/ |5 p& e4 `6 }

    ! C8 D  X* R5 c4 o6 B7 V' X, N& b# 取出模型预测概率,这个包只能用预测概率计算+ Q% b. y' B8 T4 [' X. r7 T
    p.std = mstd$fitted.values
    4 P* I$ [7 L! u$ Jp.new = mnew$fitted.values
    1 y* a- x9 j4 o+ l3 v0 \1
    8 P4 ^5 I2 F8 C, D  |8 U2 O$ g* k4 G然后就是计算NRI:$ ]' I9 R" I+ Y5 U3 [
    0 {" s6 m1 l  ]1 t- T
    dat$event <- event+ K6 [4 g* k0 Q

    3 f- s% p- M: S/ L" freclassification(data = dat," m6 ]5 J1 y7 ^0 u! S4 ]
                     cOutcome = 21, # 结果变量在哪一列/ j4 V2 [5 O9 J* D
                     predrisk1 = p.std,
    # r+ X" a8 w, N4 [- z- y2 A                 predrisk2 = p.new,
    + b' V9 W8 T2 c- e  M                 cutoff = c(0,0.3,0.7,1)- ~# h% ]' b, R9 l
                     )" x* [1 @. j& I  R' E! c
    1
    & k4 F# P, a4 A+ y. R% }5 m& O##  _________________________________________, w2 d4 z2 Y: b0 |5 }
    ##  6 ^1 q+ t0 _8 p& s
    ##      Reclassification table   
    / `$ I) P. \) F##  _________________________________________3 V7 w3 u# j, p
    ##
    7 `% v/ a9 V' J* g##  Outcome: absent 9 l8 u& [1 r% F* [) d" Q
    ##   
    7 ^7 _7 I7 h) I: A, w##              Updated Model- t1 z" y6 h- i( u  `+ q8 i8 n
    ## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified% `. l8 L+ I8 C7 f' g
    ##     [0,0.3)       121         4       0               3( p9 y( K$ @' Y1 T6 D9 ^6 Q
    ##     [0.3,0.7)       1        13       1              13
    / |1 n6 T% Z% F, b6 }##     [0.7,1]         0         1       3              25
    - T/ P; p1 @( A- Z' |& E8 b##
    0 j; \9 `$ {. C" O6 O: p##  4 \- D9 {& o$ m: C
    ##  Outcome: present 7 x( J; O5 p; u( m- I8 c4 V
    ##   2 E6 h% L* @, N1 ?3 l% r9 w
    ##              Updated Model
    " K3 p9 [% B* `# b## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified
    ! l/ P. x4 [1 c0 l) O5 I##     [0,0.3)        14         0       0               0
    9 E3 y9 p( X* j- S- I" n' L##     [0.3,0.7)       0        18       3              14
    8 N0 H8 u# _5 \6 P9 O##     [0.7,1]         0         1      52               2. W) H2 f9 Z. @: t1 \+ c+ H. \. j
    ## 8 [9 {8 a9 I0 `8 U# Z( i- v
    ##  % ~- g) r) O& S( X6 w# z3 ]
    ##  Combined Data * ?: i) y9 s0 c% C9 W. Y- g
    ##   
    " d, ]0 _3 t# v3 _##              Updated Model
    # _; L( g7 G# P) U+ A% L## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified7 h9 r! b1 L3 N& }9 x  `
    ##     [0,0.3)       135         4       0               3
    ' h/ ?2 C, K/ c1 q; d% ]##     [0.3,0.7)       1        31       4              14
    5 a/ ?6 d2 W1 [##     [0.7,1]         0         2      55               4
    # p9 a+ b0 e1 E4 B( `. \" k##  _________________________________________; i2 p6 G4 d5 e' n2 c
    ## ( w' U" t! C2 V
    ##  NRI(Categorical) [95% CI]: 0.0019 [ -0.0551 - 0.0589 ] ; p-value: 0.94806
    ; o7 I8 [! T) G9 n$ F##  NRI(Continuous) [95% CI]: 0.0391 [ -0.2238 - 0.3021 ] ; p-value: 0.77048
    . V, l- A, F% g6 M* o##  IDI [95% CI]: 0.0044 [ -0.0037 - 0.0126 ] ; p-value: 0.28396# Q- K+ Q" l& @

    + Z' p; V  m8 G/ v* D" Y1. h0 W9 x; a; I1 a2 Z0 b+ D
    结果得到的是相加净重分类指数,还给出了IDI和P值。两个包算是各有优劣吧,大家可以自由选择。% E/ x+ T5 Z. I& }. A
    % F2 @3 e7 b  D9 s7 H
    生存分析的NRI
    ' z) M% n  [- T. C还是使用survival包中的pbc数据集用于演示,这次要构建cox回归模型,因此我们要使用time这一列了。
    , W3 _2 b4 j% E  |( O8 D3 R3 b5 K
    0 l& I+ q, q$ G, L9 M; Knricens包
    ( E- A- V" f9 Y' w( @2 t/ `library(nricens)8 e7 J9 e& c+ d0 R  z- N
    library(survival)
    : u& w) y! f5 s) c) D. \5 y5 B: @5 U
    ( J6 M7 X0 q. k% W" h. Zdat <- pbc[1:312,]
    % m+ c  q. \& mdat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡0 I7 \# L3 V5 {; E+ f  Y7 W' q3 s" w6 I
    1
    1 ^8 |/ B3 p' R1 x然后准备所需参数:
      X8 ^4 k) n, Y  r! T8 O9 p5 W/ W6 g+ |, g: p5 h0 B: E
    # 两个只由预测变量组成的矩阵" @/ g( I8 `5 J& g- P
    z.std = as.matrix(subset(dat, select = c(age, bili, albumin)))
    " Q9 r3 m* L1 w3 n9 @- t4 n% ^z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime)))
    2 X2 c) i. j1 F
    & q) G( |% C( t* a; S- q# 建立2个cox模型
    ) O8 f( R& P/ G/ _. u- u+ N) a5 S- ?mstd <- coxph(Surv(time,status) ~ age + bili + albumin, data = dat, x=TRUE)
    # k( \; I5 C) ?% Qmnew <- coxph(Surv(time,status) ~ age + bili + albumin + protime, data = dat, x=TRUE)
    , J+ v# n3 k( p1 R+ B8 `+ U0 q% _2 s0 f2 y6 d. e
    # 计算在2000天的模型预测概率,这一步不要也行,看你使用哪些参数
    : W( {: r0 k" @p.std <- get.risk.coxph(mstd, t0=2000)
    ) Z, T; d4 @; d: ^p.new <- get.risk.coxph(mnew, t0=2000); d3 @, }4 P5 S
    1! l5 c( X& d7 }7 L" m. w
    计算NRI:3 J7 ]' z3 j- v
    6 q5 C) `+ J1 v5 w
    nricens(mdl.std= mstd, mdl.new = mnew, ' I* H& e5 c3 n/ p) i
            t0 = 2000,
    3 w& |/ j7 C8 m2 d! O- A: h6 Y; W        cut = c(0.3, 0.7),. E% w5 }% k5 ]7 h) t! Y2 c
            niter = 1000, ( |' X6 V5 ~1 A' @4 P. M
            updown = 'category')# T% p1 J0 b) e) M; l0 h" s0 ^9 j

    7 G7 T' Y7 W3 E/ }% n1 Q2 p) YUP and DOWN calculation:9 w8 C' x0 O, C5 q: y8 T
      #of total, case, and control subjects at t0:  312 88 144& E+ q" R) a; n- z

    1 ]# W8 l) |" D# o  Reclassification Table for all subjects:
      i0 s* d" g5 p- I; B- Y        New& O: I8 ^, d1 ~, o& U1 n
    Standard < 0.3 < 0.7 >= 0.7( e5 m* L) M; p; f: U
      < 0.3    202     7      0
    0 V! ]9 k+ x1 R- Q5 W! g  < 0.7     13    53      6
    . m! `) t/ k+ N3 g" o  >= 0.7     0     0     31+ z" K  S. R5 G& m

    " m+ z+ R; d( K  Reclassification Table for case:
    6 Y& ]$ B; S( q2 k) @$ I- H        New0 Q$ J7 y- [+ X' d
    Standard < 0.3 < 0.7 >= 0.7
    " h! P3 m7 ~4 I) ?0 s) {  < 0.3     19     3      0! z  f" l1 C( J
      < 0.7      3    32      4
    9 t6 \( W# [( b( c  >= 0.7     0     0     271 X0 g! ~( l2 i" B. c$ s
    $ j/ j0 I% P1 S' d( Q* @1 V
      Reclassification Table for control:
    ) P5 g9 P, J( e# @. d+ }$ [        New
    / T% c0 J) k9 k4 yStandard < 0.3 < 0.7 >= 0.77 t9 }: C0 [6 t
      < 0.3    126     3      0: {# H3 m. l6 U+ f
      < 0.7      5     7      2- E4 d; X8 M/ ?* w: o6 c8 D
      >= 0.7     0     0      1
    4 @$ X5 f: e' |4 D* R
    0 G# O$ ^- Y4 ]: f8 @) ^NRI estimation by KM estimator:
    6 {  N; v8 P5 v1 j4 @7 K: R/ j* G8 J1 J4 p) W7 c3 A* V
    Point estimates:
    : g5 p- x9 g9 V7 r' e6 c                Estimate6 \! p. k8 f2 C9 Y' Z: M! [" C  R
    NRI           0.05377635  j2 |! [- q! N2 e
    NRI+          0.03748660
    5 J8 [! ^) x) m* `& a* x0 b, G/ FNRI-          0.01628974) M, o; }6 N( {5 N
    Pr(Up|Case)   0.07708938
    4 |& h- f$ S- u$ ^6 ?Pr(Down|Case) 0.03960278# K. X3 n2 c& O1 q2 s  t1 c
    Pr(Down|Ctrl) 0.04256352
    2 Z& L  Q" J# p0 HPr(Up|Ctrl)   0.026273786 `0 U4 g5 L8 \' U* m: |8 M* V+ G

    7 g4 ?/ ~: @$ @- _1 p5 ]Now in bootstrap..
    : Q' M" ]* }5 J- K9 r2 }. B6 w8 _1 V) r7 V/ f/ O
    Point & Interval estimates:' F' g# O7 G6 G8 ]$ I& B
                    Estimate        Lower      Upper5 o4 N% ^6 [; G
    NRI           0.05377635 -0.082230381 0.16058172
    , K5 V/ W& u" ?( J' m- wNRI+          0.03748660 -0.084245197 0.13231776. p5 S4 @5 {6 A
    NRI-          0.01628974 -0.030861213 0.067536169 R9 N7 Z! Z& z1 g
    Pr(Up|Case)   0.07708938  0.000000000 0.19102291
    ) e  x0 A6 `* N) T( Z# y, _Pr(Down|Case) 0.03960278  0.000000000 0.15236016$ X2 N9 g4 y5 X1 T
    Pr(Down|Ctrl) 0.04256352  0.004671535 0.09863170; j3 e& i6 G5 I1 \2 `
    Pr(Up|Ctrl)   0.02627378  0.006400463 0.05998424) v% H8 p; J& X1 @
    $ B( r, g; v% S6 o) ]0 Q0 a: ?
    1
    8 Y7 z* U, w8 ]# k8 H- W4 L# N8 \1 |" L: Y' Z% t3 F9 g: M, H$ q
    Snipaste_2022-05-20_21-49-38/ O; K$ A, f: N" r1 `
    结果的解读和logistic的一模一样。' |& P" h5 m; ^- N3 H/ i
    4 ?: q7 [  J% Q8 Z3 _% o  a
    survNRI包3 q  I( }. }  h3 O. q( W# |) [; h8 `  E
    # 安装R包2 ?$ j& \( J3 N( N
    devtools::install_github("mdbrown/survNRI")/ A1 j) o" ]' i+ W# G; [6 H: h- f
    1
    " K* K% z  `6 C2 d/ a2 N加载R包并使用,还是用上面的pbc数据集。6 b- o& m& s9 c+ B$ d- q
    ! }$ j7 y, |; M: [, r* }
    library(survNRI)
    0 @  m6 S/ N: ~6 |7 I) W( Y1& X/ B5 I, ?/ Y& Z( m+ Z
    ## Loading required package: MASS
    0 N: z/ H7 n) u" F3 i/ V1$ a2 i7 v2 K0 K+ W- @3 _3 k. ~% F4 D
    library(survival)" I+ V& }1 ?9 A( |2 ^+ z
    / R+ Z+ U' F$ ]" b* d) `( O$ d5 E& ^
    # 使用部分数据
    9 _2 }" |3 N% }* U1 M0 mdat <- pbc[1:312,]2 C/ L: E' d8 V" O* K
    dat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡
    0 v3 p7 {* D, I% V) r& q; t' V# V' P5 I9 V2 @$ ~
    res <- survNRI(time  = "time", event = "status", ! E: o, D$ s6 t9 M. t9 n. p; |  [$ L
            model1 = c("age", "bili", "albumin"), # 模型1的自变量% l" I& V; K$ _  Z
            model2 = c("age", "bili", "albumin", "protime"), # 模型2的自变量
    5 _. E/ F9 a$ }, ?; O        data = dat,
    5 j. C& T6 p) t4 h        predict.time = 2000, # 预测的时间点
    * p( a1 X+ H. v+ l; l        method = "all",
    ! ]# ?6 y4 U( \) u4 s  v5 E0 `2 A        bootMethod = "normal",  
    4 f! b6 K1 p; Y. E7 W. H$ L3 ~        bootstraps = 500, 8 ]- F8 n' z& [3 i$ Z
            alpha = .05)# ]+ [7 U$ k8 Y' i

    + W' r7 o* [" x* ]& ]* Z% f1
    ' J' L1 r" S! }" k" [: a% N查看结果,$estimates给出了不同组的NRI以及总的NRI,包括了使用不同方法(KM/IPW/SmoothIPW/SEM/Combined)得到的结果;$CI给出了可信区间。
    / \! ]. \2 K. L8 M- N
    8 l& p, p; l6 {5 F+ f8 ires& d0 A6 X3 e2 ?( n+ ?. E( a! @( R
    1
    % Z# e8 ~9 D; A9 F( c! H## $estimates8 f1 M: d) V) R- k; V2 d
    ##            NRI.event NRI.nonevent       NRI- r& O, K1 [* t% T
    ## KM        0.20445422    0.3187408 0.5231951
    % E/ Z' j8 l3 W## IPW       0.22424434    0.3273544 0.55159871 E. _6 b8 T8 ^/ s$ W. K) h- e* \
    ## SmoothIPW 0.19645006    0.3144263 0.51087633 J% }: a& ^& r3 V* U0 M! H7 P
    ## SEM       0.07478611    0.2632127 0.3379988
    - i% G7 E* k& i; i5 e## Combined  0.19633867    0.3143794 0.5107181( h* r2 }* O4 K5 ?) U# J
    ## 1 X! I# ?$ u  M% ], l& M
    ## $CI" O4 g. a5 m; I/ m" g2 r' C
    ## $CI$NRI.event
    & P1 T* K2 [3 I##                     KM         IPW   SmoothIPW        SEM   Combined
    * Z% W3 E- n( f' Y9 b9 Q4 a## lowerbound -0.03915924 -0.02185068 -0.04724202 -0.1162587 -0.0473723
    7 _' H+ `( y: V1 R# l## upperbound  0.44806768  0.47033936  0.44014214  0.2658309  0.4400496
    6 J$ K2 U- K1 K( O. `& V1 {##
    $ I  A! M. l8 O  V0 {7 {& `## $CI$NRI.nonevent) i4 C* L0 f+ ?# o! V
    ##                   KM       IPW SmoothIPW        SEM  Combined4 G: _4 P- m# h" q4 Z, d
    ## lowerbound 0.1317108 0.1396315 0.1286685 0.08638933 0.1286426) c" E. X) n9 n' K2 ?! b8 s
    ## upperbound 0.7102251 0.7393216 0.6966341 0.51482212 0.6964549: W2 q/ d% [% j4 e+ G3 Q+ k+ g9 C
    ## & j$ \3 J  H+ |6 X. n. O/ F
    ## $CI$NRI5 j& u4 W" X4 o/ j* [# Y3 W6 S
    ##                     KM         IPW   SmoothIPW         SEM    Combined) C. N( R! I5 b& ?& M' G
    ## lowerbound -0.05112533 -0.04569046 -0.05439863 -0.04132364 -0.054434099 E& Q6 ?% y, m! T
    ## upperbound  0.89306122  0.92464359  0.87970125  0.64253510  0.87953153% `) X7 l6 ?1 b+ M, H, p
    ##
    % D4 S- P7 k& S9 N9 F( Y/ I##
    5 B" S: x9 l" b( L1 M5 U2 A; s## $bootMethod! M1 F" R- h, j8 w
    ## [1] "normal"( T. z, m0 T+ x  R! O& k
    ## / ~. P( Y# J* u/ }" M2 F! M5 w
    ## $predict.time
    5 F: ?" M0 l. C## [1] 2000" ]( ^7 R$ J4 C3 K/ G8 V
    ## 4 @: U5 r  q7 E4 u* o/ h3 j, Q6 ^6 L
    ## $alpha* e1 n1 {( i1 x7 O- e
    ## [1] 0.05
    ; O- K" F- b/ z$ Q4 m- j## $ Q, @; [) Q" f! a
    ## attr(,"class")
    . r0 L' v3 j- w$ [, m8 K( S## [1] "survNRI"# e. t/ F& w0 Z2 ~

    " |2 D- q$ Y$ `% }1; y& x. ]- x3 p8 t" [1 _3 M
    OK,这就是NRI的计算,除此之外,随机森林、决策树、lasso回归、SVM等,这些模型,都是可以计算的NRI的,后面会继续介绍。大家如果有问题欢迎在评论区留言。
    . j$ @% F# y* d
    ' c' @- M1 r- Y本文首发于公众号:医学和生信笔记
    ! W5 o+ N$ |, d: M$ U) Q! e/ {" z" l
    “ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。( o8 ]+ R! e2 ~0 w& S& m
    本文由 mdnice 多平台发布
    $ Q3 O% b: D2 _" {7 ~* B————————————————
    9 m$ |: F' s" O3 V6 |4 [! ], ?版权声明:本文为CSDN博主「阿越就是我」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    9 y2 q  G, L- d* e7 R: m原文链接:https://blog.csdn.net/Ayue0616/article/details/1267680062 t( @9 m8 g& A; K' K4 K

    2 [4 c- a: a% Y5 ~. z# }% b% I4 d& P
    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-4-20 21:32 , Processed in 0.467698 second(s), 51 queries .

    回顶部