QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3079|回复: 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
    / R, k: S5 W" ~0 [  ?7 U
    净重新分类指数NRI的计算& v  G2 ?! N: C. o  C
    “ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。
    : j9 U* T( S+ u. aNRI,net reclassification index,净重新分类指数,是用来比较模型准确度的,这个概念有点难理解,但是非常重要,在临床研究中非常常见,是评价模型的一大利器!
    9 h* ]1 v2 [# E' M" j1 b# N) O, n0 f9 t4 B; J( q- E# S6 [; B+ J6 W
    在R语言中有很多包可以计算NRI,但是能同时计算logistic回归和cox回归的只有nricens包,PredictABEL可以计算logistic模型的净重分类指数,survNRI可以计算cox模型的净重分类指数。
    + y6 n8 y: K" t% c2 f4 L; O1 a& Q0 Y1 u4 @) q% A
    logistic的NRI3 \1 `, {# |  S3 t' c+ f
    nricens包1 J: c3 n2 b: E: [
    PredictABEL包
    " U6 m' w$ r& }- H0 |- N( b生存分析的NRI( P) e6 ?2 m0 x, m: L
    nricens包
    - Y2 \- j, R( d" P7 osurvNRI包1 B$ f" ^4 k# z7 a
    logistic的NRI7 k  n+ G& k4 \; m* ~0 C: `
    nricens包
    ( I0 T( p( Q/ Z: }, v( A. L#install.packages("nricens") # 安装R包
    * |* Q( Q! B- x3 i! Hlibrary(nricens)
    ( y+ U& F" v) p* J8 T/ @* r) I12 g1 I3 V1 n  j8 I$ t
    ## Loading required package: survival" E4 L/ r. [# B1 C
    1
    * ^; s! _- t  A使用survival包中的pbc数据集用于演示,这是一份关于原发性硬化性胆管炎的数据,其实是一份用于生存分析的数据,是有时间变量的,但是这里我们用于演示logistic回归,只要不使用time这一列就可以了。- F( D- }( A, o' R( L

    1 {" d- H+ _" e, _library(survival)
      u" k, V! v" p  _( S' L
    $ e7 G2 h  Y# p# f; l7 w# 只使用部分数据
    , Y4 d5 e2 q' A0 jdat = pbc[1:312,]
    ( d3 y$ i( `  W# T/ |& A0 Tdat = dat[ dat$time > 2000 | (dat$time < 2000 & dat$status == 2), ]
    5 M* @+ @5 W/ j. d- X' T% o5 x! H7 J
    str(dat) # 数据长这样
    2 d& x/ V: ^2 u1 w1 Y: Y1
    " o/ V  H7 K% o# P/ ]& e## 'data.frame': 232 obs. of  20 variables:
    / x, O3 q5 y8 ~) c: h! i##  $ id      : int  1 2 3 4 6 8 9 10 11 12 ...
    4 C1 ^% i3 J" l# t5 M1 t- U; A##  $ time    : int  400 4500 1012 1925 2503 2466 2400 51 3762 304 ...' L+ o% M! |, d9 z0 p; r
    ##  $ status  : int  2 0 2 2 2 2 2 2 2 2 ...$ n, S: r' T& O
    ##  $ trt     : int  1 1 1 1 2 2 1 2 2 2 ...
    , c  a- a6 o5 i; d& v##  $ age     : num  58.8 56.4 70.1 54.7 66.3 ...; u: h5 _& ~5 z- Z7 w, C+ @3 D
    ##  $ sex     : Factor w/ 2 levels "m","f": 2 2 1 2 2 2 2 2 2 2 ...
    % h7 t7 S( j, c& `$ G$ O6 L##  $ ascites : int  1 0 0 0 0 0 0 1 0 0 ...; L% L# M8 P8 q" B( O; z4 r
    ##  $ hepato  : int  1 1 0 1 1 0 0 0 1 0 ..." z, ^+ S1 F' q$ j' V4 w. A$ S$ D
    ##  $ spiders : int  1 1 0 1 0 0 1 1 1 1 ...
    9 @; C* x; o6 l6 N- I" H6 J+ _% w2 s##  $ edema   : num  1 0 0.5 0.5 0 0 0 1 0 0 ...
    9 v' d/ D7 S' c##  $ bili    : num  14.5 1.1 1.4 1.8 0.8 0.3 3.2 12.6 1.4 3.6 ...
    ) D0 p8 d; _9 @% t' ~# z( H##  $ chol    : int  261 302 176 244 248 280 562 200 259 236 ...: z) o7 G9 K) h2 c. g) k# A
    ##  $ albumin : num  2.6 4.14 3.48 2.54 3.98 4 3.08 2.74 4.16 3.52 ...
    0 v6 t4 W0 T7 e' J* G# b##  $ copper  : int  156 54 210 64 50 52 79 140 46 94 ...
      D. |4 @/ Y: Z$ L##  $ alk.phos: num  1718 7395 516 6122 944 ...- v# i  j2 s. U, u& D: Z
    ##  $ ast     : num  137.9 113.5 96.1 60.6 93 ...& w! N2 B+ R: m% f+ b" D5 `2 W
    ##  $ trig    : int  172 88 55 92 63 189 88 143 79 95 ...
    : I( w8 h: p8 g1 |# H; w  j- V% H##  $ platelet: int  190 221 151 183 NA 373 251 302 258 71 ...' C- {  y! H" [  `8 {
    ##  $ protime : num  12.2 10.6 12 10.3 11 11 11 11.5 12 13.6 ...  B0 t' @$ ]8 G
    ##  $ stage   : int  4 3 4 4 3 3 2 4 4 4 .... x' u3 J7 \5 R  ]8 i
    2 f9 M) O8 D+ u4 Y) i! E+ ~5 l' N
    1
    / O' n  }8 V5 ~  g9 W1 xdim(dat) # 232 20
    # J5 f' N* @, e2 s1
    % e5 e) p5 f  K8 a  [  x% W4 X## [1] 232  20
    * ?6 @* k4 B5 D1; y; ~' h$ S' B8 f
    然后就是准备计算NRI所需要的各个参数。
    + x1 H' n8 t7 Q& z7 I/ r/ t2 n, _+ ]& S; d
    # 定义结局事件,0是存活,1是死亡( Q0 f: ]: ?, L' H4 n: ~! I  }0 x# R# n
    event = ifelse(dat$time < 2000 & dat$status == 2, 1, 0)
    & Q& U, o0 Y6 X: P! f5 l1 J* [, I) R9 a( e
    # 两个只由预测变量组成的矩阵1 O" i* z  @4 W2 F
    z.std = as.matrix(subset(dat, select = c(age, bili, albumin)))
    8 ?0 i1 ?8 Q, [8 o  H$ F- sz.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime)))
    / ~3 _1 |7 w% j+ o
    ; W6 u' Z8 Z) @( }# 建立2个模型, f( F1 n/ d, {9 I5 s/ v, h
    mstd = glm(event ~ age + bili + albumin, family = binomial(), data = dat, x=TRUE)
    $ F% R- k- E+ p) p/ W% \mnew = glm(event ~ age + bili + albumin + protime, family = binomial(), data = dat, x=TRUE)
    6 A2 K4 J3 o. s  d! v& Q+ p3 L
    & x4 X7 ^- s6 M( H8 i+ O8 _2 [# 取出模型预测概率  |1 O: T% A' D. N. l; S" d6 Q
    p.std = mstd$fitted.values: |, p2 P0 l1 |0 |
    p.new = mnew$fitted.values4 }! g- k( l; U$ i# Y' z. q* g: Z4 s
    ' p- m% R* L+ ]  T. a4 z: x" H/ z# y
    1( B% Q- f. P4 H3 a- J6 t' X- ^
    然后就是计算NRI,对于二分类变量,使用nribin()函数,这个函数提供了3种参数使用组合,任选一种都可以计算出来(结果一样),以下3组参数任选1组即可。 mdl.std, mdl.new 或者 event, z.std, z.new 或者 event, p.std, p.new。
    5 h6 Q- y; t% d( P0 V& M
    1 ]8 l1 l; j/ z# _# v3 R& T0 S' o! |# 这3种方法算出来都是一样的结果
    - Z3 u" U& T: q! ~4 o6 U: [; ~$ O1 }  g% _4 u3 P; [
    # 两个模型0 J4 d0 m9 K2 Z$ J4 D9 |/ I
    nribin(mdl.std = mstd, mdl.new = mnew, + f0 D/ y& c; b# e1 T' F. o
           cut = c(0.3,0.7),
    1 P) U/ C; z+ m1 j       niter = 500, 2 W" O" ^9 d! n
           updown = 'category')
    , z1 r0 v$ X5 W
    # ~& i$ O% U6 C, v, r& j# I# ~# 结果变量 + 两个只有预测变量的矩阵2 C9 k$ g2 h( @9 L
    nribin(event = event, z.std = z.std, z.new = z.new, ( z( `( K7 C1 d5 r6 }: n) b
           cut = c(0.3,0.7), . l2 W/ K" ~; V1 N. V6 ?
           niter = 500, , H& F% o) ~- N" t, |
           updown = 'category')
    " @# w+ M% g: `/ B$ {( @& l6 I3 x$ `
    ## 结果变量 + 两个模型得到的预测概率
    ' [; o8 k: K( T& N% f0 Xnribin(event = event, p.std = p.std, p.new = p.new, ! n8 i7 B! X1 I) S
           cut = c(0.3,0.7), 1 R0 H6 k  {$ R! T) c) |* ?
           niter = 500,
    ; q* W0 Z; ^, r1 K( B3 [       updown = 'category')
    5 \6 ]( j9 t, g7 V0 B, q* r" K5 ~+ L4 T0 K, w3 x* X) @+ Q
    1
    " O) y( I, k4 F1 ]% n' j其中,cut是判断风险高低的阈值,我们使用了0.3,0.7,代表0-0.3是低风险,0.3-0.7是中风险,0.7-1是高风险,这个阈值是自己设置的,大家根据经验或者文献设置即可。
    2 ]! [8 m" m8 c: ^  y# d: v  y8 D' S: v5 u6 `! w: s, _& e
    niter是使用bootstrap法进行重抽样的次数,默认是1000,大家可以自己设置。/ L' j. ]! ~, ?# H

    + f$ p  Z" w! u. t% `; z0 {updown参数,当设置为category时,表示低、中、高风险这种方式;当设置为diff时,此时cut的取值只能设置1个,比如设置0.2,即表示当新模型预测的风险和旧模型相差20%时,认为是重新分类。/ L* G! W# p" ^+ }! \5 s' D

    ' v! S' m% n6 }, f& T( M) B1 O, l( X/ f# C上面的代码运行后结果是这样的:/ r* n/ x% o; \( M& i- Q5 a8 E
    3 T/ a4 ]5 R! B* S6 X( [/ q
    UP and DOWN calculation:& S9 G$ o' h# X5 D4 g0 H8 p
      #of total, case, and control subjects at t0:  232 88 144
    ( m% i8 k7 b4 q: n( n- J" F! ?
    1 A. {6 m0 W* H' Y( c0 k' ~  Reclassification Table for all subjects:3 H% u; c  d; z
            New
    / O! E; {7 O+ H" |0 a% V  UStandard < 0.3 < 0.7 >= 0.7
    , ?3 t$ F% X* r8 ?8 _  < 0.3    135     4      0
    . _0 n5 w- _+ r7 R, L, P# f( `  < 0.7      1    31      40 B; H1 g9 e: i  f' v6 i
      >= 0.7     0     2     55
    3 @6 \) L, s" o- E* n0 U( _% a0 _3 `  K; j9 ^
      Reclassification Table for case:
    * {# x" ?" n+ K' @9 y        New1 Q8 h5 b- _5 c* c- K9 C
    Standard < 0.3 < 0.7 >= 0.7
    6 Z; @6 w/ c, A2 r5 n  < 0.3     14     0      0
    6 T/ n& A3 b( l$ m$ M- }. M  < 0.7      0    18      35 s* `" L8 o6 e. u. H
      >= 0.7     0     1     52: k) W% a, r! p8 R+ f1 d% m

    : l; P, Z6 ^) i  Reclassification Table for control:+ R$ P* z- a! u" [, |5 r/ Z
            New
    $ S3 t; i% D4 R5 y7 y- A# \% qStandard < 0.3 < 0.7 >= 0.76 Q" B0 L3 {$ L" j
      < 0.3    121     4      03 Z- k6 b* m9 C2 ]. [
      < 0.7      1    13      1: ^' ]7 e3 C$ G3 h
      >= 0.7     0     1      3% ?0 g1 I3 N6 q- `7 H
    + H( |$ E( `$ l4 W+ L* X
    NRI estimation:
      I2 ]% k  |/ ZPoint estimates:- x# M, g( ^8 k% T: I
                      Estimate4 R, M; o! T# q6 C
    NRI            0.001893939. V) p$ [  S# `; e* i  A1 @2 s4 h
    NRI+           0.022727273: Y2 U; O6 g) a
    NRI-          -0.020833333
    . U/ K2 J7 s. s8 i9 O1 ZPr(Up|Case)    0.034090909
    8 J0 q2 @( V6 w1 F6 UPr(Down|Case)  0.011363636
    " q6 |$ `: n" n6 J& ~. B6 P% YPr(Down|Ctrl)  0.013888889
    $ d: L" \$ M$ v( K3 y! I# lPr(Up|Ctrl)    0.034722222
    ! k! O8 Z1 c) {% E
    ; M3 a5 L4 H+ tNow in bootstrap..0 r# }4 M% _, @4 V( S3 e
    + Q# A- K+ Q% O; g( O
    Point & Interval estimates:- ^+ @4 @# ?1 j2 c  \, r
                      Estimate   Std.Error        Lower       Upper! }$ `: l2 W+ O4 a
    NRI            0.001893939 0.027816095 -0.053995513 0.055354449
    7 z  B1 l1 \& D0 X: a$ n  @NRI+           0.022727273 0.021564394 -0.019801980 0.065789474+ G# J, K% I3 T: N
    NRI-          -0.020833333 0.017312438 -0.058823529 0.007518797, R0 }5 X$ v4 S7 m( j1 ^* @
    Pr(Up|Case)    0.034090909 0.019007629  0.000000000 0.0721649481 ^2 k! x* r) O
    Pr(Down|Case)  0.011363636 0.010924271  0.000000000 0.039603960' F+ ^$ b2 @2 ^
    Pr(Down|Ctrl)  0.013888889 0.009334685  0.000000000 0.035211268- M! M/ C9 \1 [( L  `' x: B
    Pr(Up|Ctrl)    0.034722222 0.014716046  0.006993007 0.066176471
    4 D! _, a' w* @
    % B. Z& v9 w5 U: v0 ], @  {, J1
    & q$ w) Y1 J  ^3 G7 M) c3 T首先是3个混淆矩阵,第一个是全体的,第2个是case(结局为1)组的,第3个是control(结局为2)组的,有了这3个矩阵,我们可以自己计算净重分类指数。
    + s) r0 D2 @- Z% k0 ]
    , w+ V1 V9 F5 g' s3 o/ b看case组:" D( Q2 C# J3 _3 d9 A4 ]8 B
    5 ]* Z7 i/ w% L# x9 k
    净重分类指数 = ((0+3)-(0+1)) / 88 ≈ 0.022727273( Z' f0 `' Z/ a; F5 e
    " ]1 n8 u0 n! I6 _; _
    再看control组:7 Z% V( i3 P: c4 G
    ) R0 _, n8 {' h
    净重分类指数 = ((1+1)-(4+1)) / 144 ≈ -0.020833333
    , H; H& L( o* T/ @" W  d1 h" Z3 P  C' V. L7 w% C: V
    相加净重分类指数 = case组净重分类指数 + control组净重分类指数 = 2/88 - 3/144 ≈ 0.000315657; h4 x: |4 h( G: v0 w

    " J# k+ x$ Q) K, o2 o% G; [7 }再往下是不做bootstrap时得到的估计值,其中NRI就是绝对净重分类指数,NRI+是case组的净重分类指数,NRI-是control组的净重分类指数(和我们计算的一样哦),最后是做了500次bootstrap后得到的估计值,并且有标准误和可信区间。
    $ L7 X' A1 _% p$ K) t
    # T' }" g+ u: E. j" t最后还会得到一张图:
    . @  m* n" @2 @7 a' y  p' {  ^3 n6 A! `1 V: Q
    这张图中的虚线对应的坐标,就是我们在cut中设置的阈值,这张图对应的是上面结果中的第一个混淆矩阵,反应的是总体的情况,case是结果为1的组,也就是发生结局的组,control是结果为0的组,也就是未发生结局的组。
    6 B& _. _* i% K9 ?* n6 E; @8 _* D6 {; x/ i$ e: v; H0 b/ h
    P值没有直接给出,但是可以自己计算。1 M! h# ?0 {6 z
    * C: L8 v, S' N- |( h
    # 计算P值
    $ h! c- d4 b$ w: X! L1 \3 Rz <- abs(0.001893939/0.027816095)
    0 h& Q7 Y$ [( ^1 ?) kp <- (1 - pnorm(z))*24 t( L0 c) {& r' m- G5 d* F
    p
    7 N6 v, T* d2 U7 B) H17 R. U" B" ^. s1 Y9 k: p3 ~% y
    ## [1] 0.9457157, O/ k. C: {8 h2 v) e
    1" F4 ^! Z3 ~+ x7 I
    PredictABEL包
      W, `4 n% n2 _  I: G: P$ Q& V#install.packages("PredictABEL") #安装R包
    - _+ d8 n' o0 e, D+ D6 Ylibrary(PredictABEL)  
    + M2 p, M( j' t5 w& `3 H9 [$ e) a
    # 取出模型预测概率,这个包只能用预测概率计算! L7 G  q$ D' s; }
    p.std = mstd$fitted.values, }7 m  P- b: X' |/ q' A$ J
    p.new = mnew$fitted.values . o4 u0 l; M% }5 r+ X
    1( o- C5 P! b# N9 p4 o
    然后就是计算NRI:7 ?: Q0 I, m$ g% c7 ~, e- c- w) S

    ' t6 ^0 J& p2 _) G& v3 odat$event <- event
    0 A% w  \# w7 R; Y' t
    ' d+ @# q0 {& V# ?6 rreclassification(data = dat,
    , \) n( i, z( L1 @" [0 Q2 i1 \                 cOutcome = 21, # 结果变量在哪一列1 J/ m6 Y) m; C" u; L( s4 G0 s3 U
                     predrisk1 = p.std,
    , q8 e( }# F2 _. Q8 J                 predrisk2 = p.new,
      e. E# Q/ z. G$ U! O                 cutoff = c(0,0.3,0.7,1)' o* r. ]: A' _
                     ); s/ @9 C% r/ r
    1
    ( R/ x, f! a5 R7 J2 y. @, t/ B3 g7 f% q4 N##  _________________________________________+ d5 d9 F) z8 @* J
    ##  9 S/ z3 H6 Z+ K" C2 z0 ^) M
    ##      Reclassification table   
    + }' n' `0 q9 l/ G1 X/ }1 O) D##  _________________________________________' L) J0 W* I2 d6 {
    ## ( b( a: I6 F7 F& |
    ##  Outcome: absent 6 E3 c; r: J1 S- z: @1 g5 G# w7 h
    ##   
    9 {! b, k7 ^2 `" d9 x) p5 ^+ }##              Updated Model
    ; \( W& S) J2 N8 `; p# O0 I## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified) T9 D. a6 ~; V6 s- Q. Z
    ##     [0,0.3)       121         4       0               3" [6 o/ x$ f9 R- I2 i& {) c
    ##     [0.3,0.7)       1        13       1              13. R1 ~$ G3 Y6 z; d! \" j
    ##     [0.7,1]         0         1       3              25
    & w* z3 C( D9 A3 n0 }2 K% Q##
    7 r7 v2 [; _9 N, d- v: ~##  , @5 g- D2 a% L6 B/ e
    ##  Outcome: present
    9 f- {0 }# z3 W##   ) u3 e8 B3 m  @$ H3 R4 [
    ##              Updated Model
    / d1 y" i, C8 Q5 ]  x, g## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified
    0 R) N/ m' t4 [! q3 p##     [0,0.3)        14         0       0               06 \( B2 @8 @' o* y) r
    ##     [0.3,0.7)       0        18       3              14
    ( Y3 X; X$ |% }. y- o2 r##     [0.7,1]         0         1      52               2& @$ R. r6 L$ z2 I- d
    ##
    # ]3 y* _% |$ k! w( @% h4 P##  
    1 z+ D* S+ f/ U0 X: Y7 h##  Combined Data
    - S5 `- T' C# E( _( o. d: s& j##   
    & B% w& t7 B& F3 Q5 B  h( G% Y##              Updated Model6 @2 z/ b8 I( u$ c# `: R
    ## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified; {# l" k, l' X2 O6 |9 \- X; `
    ##     [0,0.3)       135         4       0               3
    / o+ N/ z' ~4 Z" d& j9 k# m##     [0.3,0.7)       1        31       4              14! w& _( E: @: B. r% {6 d# G7 L
    ##     [0.7,1]         0         2      55               4
    1 h) n+ d8 M; d& w% i) A* E% C##  _________________________________________
    % Z* X% C' b" G" [( Y## : f# _1 y- I, w# G* O% U& K
    ##  NRI(Categorical) [95% CI]: 0.0019 [ -0.0551 - 0.0589 ] ; p-value: 0.94806 . }" u; l+ X  x/ P/ f5 q2 A; N
    ##  NRI(Continuous) [95% CI]: 0.0391 [ -0.2238 - 0.3021 ] ; p-value: 0.77048
    $ N; n; H$ ^6 o" s/ r! b##  IDI [95% CI]: 0.0044 [ -0.0037 - 0.0126 ] ; p-value: 0.28396
    - F0 d7 O1 a+ c0 U% v# n8 x7 g; n; X# B6 V6 I7 z
    1( w& y6 n" q7 O/ }, I
    结果得到的是相加净重分类指数,还给出了IDI和P值。两个包算是各有优劣吧,大家可以自由选择。6 T; l7 S/ |. }, t# e1 z- x) \

    / ?; i% }8 R3 o% S+ C生存分析的NRI7 y# Q! A( R9 @8 S$ j, @/ L' Z
    还是使用survival包中的pbc数据集用于演示,这次要构建cox回归模型,因此我们要使用time这一列了。( c4 o# C2 G7 T' u. D
    9 z7 j, z4 L/ _6 ?- \# L0 k
    nricens包
    + u9 ~5 l: O" A* X& Y: d4 Ylibrary(nricens)4 l" d( x4 u7 H% N7 [
    library(survival)
    * T# C1 t% f6 k. x! Q2 S& C
    $ W6 |/ w3 e; _9 Q" j! n# L8 Ddat <- pbc[1:312,]+ T5 ^/ C1 f& k" I
    dat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡
    2 [" l1 u! x" i: S10 q! {4 x4 q8 Y1 e5 {1 V
    然后准备所需参数:
    ' o0 _" X4 t9 X5 W. s3 A# I' O6 }# V' w/ @% H
    # 两个只由预测变量组成的矩阵7 d% b7 U' C' V: G2 G4 X8 [7 K
    z.std = as.matrix(subset(dat, select = c(age, bili, albumin)))
    . Y- t9 [, u! J5 Nz.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime))): H9 K: T3 I+ f7 e5 U" a$ i- }" Y

    : F. C5 [, e  O: D5 X6 y, V" O# 建立2个cox模型) t' k! F4 z) X/ u6 U7 N( d
    mstd <- coxph(Surv(time,status) ~ age + bili + albumin, data = dat, x=TRUE)
    5 J2 M( c2 y* T: z" ymnew <- coxph(Surv(time,status) ~ age + bili + albumin + protime, data = dat, x=TRUE)
    7 `" D& J- ~* s7 D% D, t
    0 o1 J# a: v5 G- F0 ~1 H  Y1 @# 计算在2000天的模型预测概率,这一步不要也行,看你使用哪些参数
    , q$ T5 ~+ W) V2 h$ l, d% qp.std <- get.risk.coxph(mstd, t0=2000)
    ! ^7 d# Y$ g. \( i% W4 Z2 x: up.new <- get.risk.coxph(mnew, t0=2000)5 D6 I) r) E5 O; ^9 h
    1
    ; S3 n# W, l2 ^# ]% I5 y( i1 b4 w计算NRI:
    ; \; A; k& R; _4 Y1 y+ Y; Q
    . w# Q. x$ m$ U) j, e" _. T9 Pnricens(mdl.std= mstd, mdl.new = mnew,
    ' Y' W7 h$ x- P3 B7 d* O        t0 = 2000,
    # {1 g1 S. x) Y/ o1 Y9 d        cut = c(0.3, 0.7),
    + w+ R# [" S/ C        niter = 1000, / T4 g/ x" b7 D
            updown = 'category')
    9 c# @8 r" o0 {, ?6 t! Y8 w- s$ c% `
    UP and DOWN calculation:
    * O& N/ T/ |2 W  #of total, case, and control subjects at t0:  312 88 144  |/ z5 L. s% \5 l$ R. q( B

    # O% M4 b3 n8 }" p8 @, M! [  Reclassification Table for all subjects:* X; a* e" v" |1 t# T
            New
    8 m( `2 L1 b3 O; c# eStandard < 0.3 < 0.7 >= 0.7/ R: w6 [% o9 E1 s" g2 B" l
      < 0.3    202     7      0. |: K, s% V1 z8 y5 ~# q
      < 0.7     13    53      6
    $ q0 l! T/ C6 ]% x, K/ O  >= 0.7     0     0     31
    / Q$ u' V& \; U/ K: e
    ( j$ k& D* b  `5 i  X6 X4 P7 @  Reclassification Table for case:: y" P! R- f9 a6 _6 u! B+ V2 l
            New! ?$ _$ K$ ]1 X
    Standard < 0.3 < 0.7 >= 0.7
    ! A% [" b9 |0 k$ E0 h7 k  < 0.3     19     3      07 G8 r, Z* X! ?0 N
      < 0.7      3    32      4
    5 B$ T8 d1 F' Y/ e1 F2 i" p: M  >= 0.7     0     0     27
    8 x: d2 q+ g+ N, {9 x3 S
    , }- I. R% ~, V/ i+ N: P9 {$ D  Reclassification Table for control:
    9 m5 I) }1 s1 p3 M: L        New3 R: O) m9 z4 W2 B( c3 o6 K
    Standard < 0.3 < 0.7 >= 0.7( @2 D! i0 H1 {- v8 W* M$ l" m
      < 0.3    126     3      0
    % t0 ]# e1 c! C. ?2 |2 i4 d  < 0.7      5     7      21 C. [" r% K; T- w8 K4 p
      >= 0.7     0     0      1! z2 C% {2 t3 e

    ' N, N, u  `; [2 UNRI estimation by KM estimator:7 `! Y+ ]6 y$ `* i9 k

    " A3 o8 n, R" j- d; k# ^& m" ZPoint estimates:- [6 v& e  B& p9 f( e9 N) j, m/ j; P
                    Estimate7 J3 z/ D0 s2 k! j* W/ e
    NRI           0.053776355 |  i6 b9 I$ s" d: F3 B
    NRI+          0.03748660
    - t8 e7 U5 m4 v' `# LNRI-          0.01628974" D+ H3 O! U1 }! c) k6 S! L; {
    Pr(Up|Case)   0.07708938( @7 w# F' K0 H$ U9 a
    Pr(Down|Case) 0.03960278# V+ ~; [) X" c$ j
    Pr(Down|Ctrl) 0.04256352
    . U6 G) r0 X% K2 a0 u2 d# N8 pPr(Up|Ctrl)   0.02627378
    7 X" m/ d4 ?1 s, E: g- a. P2 e4 r7 C* m1 @# C
    Now in bootstrap..
    5 W4 m+ C9 R' G2 N+ i- J  ], G- V: {1 N5 {# f* g
    Point & Interval estimates:
    - R, z' ]$ R0 l$ w6 j1 P                Estimate        Lower      Upper$ M- \3 ?) r+ P) L
    NRI           0.05377635 -0.082230381 0.16058172
    1 F* V$ ^7 s& X/ m2 T/ q6 I- e- JNRI+          0.03748660 -0.084245197 0.13231776, P  T7 P. b0 a( d/ D
    NRI-          0.01628974 -0.030861213 0.06753616
    ) S& J. o9 I, T1 X( m. ?9 ~Pr(Up|Case)   0.07708938  0.000000000 0.19102291/ j& W9 m3 u7 L9 u' Y
    Pr(Down|Case) 0.03960278  0.000000000 0.15236016
    ( n' i! I( t# W) k- Q) ^, w; _4 b7 |Pr(Down|Ctrl) 0.04256352  0.004671535 0.09863170  e2 o, v7 S! {
    Pr(Up|Ctrl)   0.02627378  0.006400463 0.05998424
    8 Y( F2 X8 a& d
    : z' A- D( K: h1 w5 B! C1) I  K- g0 x; T9 R4 k  K

    & N' [4 J1 W; B2 cSnipaste_2022-05-20_21-49-38
    4 h5 H, Q- A# ?' Z! Q$ s9 |0 b结果的解读和logistic的一模一样。1 o/ `. l* O% B) X
    5 o% q  Z' P6 m7 u6 G& B, S* Z+ D4 i
    survNRI包
    1 A! o& x5 |6 E+ ?. t6 p. H# 安装R包  a6 M5 d  Z5 s, P( }6 y1 M
    devtools::install_github("mdbrown/survNRI")7 z- {! c" x; h: C  l5 k
    1
    1 y* ^( D/ X2 B4 [0 Z8 C( L2 \加载R包并使用,还是用上面的pbc数据集。
    4 m- _7 Z) N$ K2 |) X. Q; U: F6 o6 v
    library(survNRI)
    4 K! v- e4 [; V; `0 o6 H5 F1
    1 Q" u6 e- n( _8 X( |  r! r## Loading required package: MASS
    : }5 h! w8 w* I. W1 V+ ^15 \% @7 V* @, E% B
    library(survival)
    ; C  a0 t1 B+ l6 `- @$ ]6 p7 t% O- ~+ E2 M* }1 F
    # 使用部分数据: Z) v4 l4 |( K- K
    dat <- pbc[1:312,]
    ' e3 L3 a! o, a. M% V6 Ldat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡
    + ~  G& E4 z( s( }# b
    8 t5 f( r" f& N) {8 P  Lres <- survNRI(time  = "time", event = "status", / y  M9 \5 ?8 P
            model1 = c("age", "bili", "albumin"), # 模型1的自变量# v) E' M2 S9 T5 r1 ^+ Y# O+ G: F
            model2 = c("age", "bili", "albumin", "protime"), # 模型2的自变量
    & V2 d+ x: c2 W4 {" i        data = dat, % l5 S7 e2 V- q% \3 Z- ]0 \3 \
            predict.time = 2000, # 预测的时间点' }5 V% L, `  t  `
            method = "all", ) q$ H9 H1 x1 J8 s! G+ d
            bootMethod = "normal",  / e% l- f0 n9 W! Z# v6 G+ ?$ d
            bootstraps = 500, , Y7 `% {& y! @0 b
            alpha = .05)
    ' m# P. ]' N6 ~- b( e' {
    . Z& u/ `$ Y7 F$ r10 P2 _3 I( \, p1 I
    查看结果,$estimates给出了不同组的NRI以及总的NRI,包括了使用不同方法(KM/IPW/SmoothIPW/SEM/Combined)得到的结果;$CI给出了可信区间。& K, @0 E! O* c
    % g0 g% h' V) C. u/ z
    res5 S5 K& O$ i4 k0 H) v& M/ s! |5 m
    1
    3 e* T( q  Q; X: l' a* r6 X8 g## $estimates
    6 W) d5 D, I: q  j0 \6 w##            NRI.event NRI.nonevent       NRI0 o( a' Z( q. X& o! R8 Z4 Y) S# D- L
    ## KM        0.20445422    0.3187408 0.52319513 O0 g2 ~; X: ~  ^9 @4 L9 `1 V: f+ I
    ## IPW       0.22424434    0.3273544 0.5515987  J2 |5 z6 ~. L
    ## SmoothIPW 0.19645006    0.3144263 0.5108763* M( U/ b1 N) p  F& j
    ## SEM       0.07478611    0.2632127 0.3379988
    7 S+ }& N- m8 F3 E, O; ?## Combined  0.19633867    0.3143794 0.5107181- d6 q6 J4 L( ^) ?
    ##
    - W) d/ M& z* A, R+ \" G( w3 J8 l2 y## $CI
    & f( m/ B" r7 v  T- n6 c+ {## $CI$NRI.event  B7 y$ q9 Z$ H; T: [# P- f, S" v- i* ^
    ##                     KM         IPW   SmoothIPW        SEM   Combined
    6 V5 a+ D, S, N& \! o$ d## lowerbound -0.03915924 -0.02185068 -0.04724202 -0.1162587 -0.0473723, M2 V0 G2 u$ j% A
    ## upperbound  0.44806768  0.47033936  0.44014214  0.2658309  0.44004965 D; ]  s% u. T7 @) y7 n4 v& _4 C9 C
    ##
    2 C8 O  V; u4 m4 k5 p& t  g# s& W## $CI$NRI.nonevent* e5 i% U/ d) R# W0 h" i
    ##                   KM       IPW SmoothIPW        SEM  Combined
    % }4 J/ d0 v9 ~5 X## lowerbound 0.1317108 0.1396315 0.1286685 0.08638933 0.12864269 u/ Y' D4 O- n) I' E) O2 B7 r
    ## upperbound 0.7102251 0.7393216 0.6966341 0.51482212 0.69645492 c$ p3 \! z: \1 @2 s( o1 Z/ ?  B
    ## ' }  r, G+ \8 Y/ ?- T9 y; a3 O
    ## $CI$NRI/ t# K  i, G' }( {7 J" z
    ##                     KM         IPW   SmoothIPW         SEM    Combined0 U' a, S& v" G
    ## lowerbound -0.05112533 -0.04569046 -0.05439863 -0.04132364 -0.05443409
    6 L) {7 t  E. ?5 ^## upperbound  0.89306122  0.92464359  0.87970125  0.64253510  0.87953153
    . c; i7 g8 \9 N1 E; H. }! m* f+ Q##
    . m. }, ^# z, {: o! S5 u0 g, f" Y##
    9 Q' k1 o! q9 Z4 q## $bootMethod
    3 R- m& F% D$ p; T9 x$ X3 A- T## [1] "normal"
    0 h( `2 q0 `0 D* [. N: U- Y## 0 ?* Y  v! z. p( Q, a0 Q
    ## $predict.time' x" f4 \% ?9 ^! a9 l3 s6 N
    ## [1] 2000
    5 ?- {8 j% W9 c##   t& i: \; v8 Z; l1 |5 v
    ## $alpha
    3 O+ s/ b6 d5 q3 x1 P6 Y) W6 G, l## [1] 0.05- x6 o4 I4 j$ }9 v' V& a) f
    ## ( k7 h- ~' Q# x( `
    ## attr(,"class")
    $ ~$ S5 v* Q* }3 Z/ l9 Y7 _, B## [1] "survNRI", n* O9 ^+ K2 v6 K+ q9 l

    $ _% m! V+ p! d) }1
    ' ^5 J" n+ U) U/ p# `4 s% i; R! NOK,这就是NRI的计算,除此之外,随机森林、决策树、lasso回归、SVM等,这些模型,都是可以计算的NRI的,后面会继续介绍。大家如果有问题欢迎在评论区留言。1 P3 z8 `3 @  D" S; M+ x7 k9 X$ Q

    # T$ o9 u, Z8 A7 c本文首发于公众号:医学和生信笔记
    $ i- W, Z3 ~0 Q+ b
    6 f$ O$ U/ ?/ S* r) E“ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。
    # v' O5 Y% w% C! d本文由 mdnice 多平台发布
    , J5 R" t- Y( E————————————————
    1 g9 b  T5 C  E; O* R版权声明:本文为CSDN博主「阿越就是我」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。4 `9 D4 l1 h8 R' x8 u# d; t! X
    原文链接:https://blog.csdn.net/Ayue0616/article/details/1267680062 a8 r- t0 P/ I9 ?

    # U1 z( {# `- J/ _5 G" B4 a" X
    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-7-29 21:26 , Processed in 0.434808 second(s), 51 queries .

    回顶部