QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2343|回复: 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

    0 o# x6 U8 G) }7 ~# y净重新分类指数NRI的计算
    : M+ N- D2 W1 b: `& B: S“ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。
    : ]4 y+ d+ \8 @3 S" O) uNRI,net reclassification index,净重新分类指数,是用来比较模型准确度的,这个概念有点难理解,但是非常重要,在临床研究中非常常见,是评价模型的一大利器!
    , y& D5 |/ _+ F5 g( R& ?  d" [: I5 N: Q0 x; a" U
    在R语言中有很多包可以计算NRI,但是能同时计算logistic回归和cox回归的只有nricens包,PredictABEL可以计算logistic模型的净重分类指数,survNRI可以计算cox模型的净重分类指数。# w' {  N3 d. ~1 {
    4 |; A' \6 @! p) [0 S
    logistic的NRI
    0 P2 @; F. E, R. h" S% a9 z- Onricens包& e6 L& O# R4 I" l
    PredictABEL包8 f) t, d! x, x  ]+ A5 i/ J: Z& K9 P
    生存分析的NRI
    9 w1 j, u2 Q7 l, K5 f3 X* L. Unricens包7 A: ^/ s( R* }7 ~, {
    survNRI包1 x: F1 x: _0 c( r( ?& q  M
    logistic的NRI
    1 s1 X) B5 K' u( M/ \9 w2 k0 v3 s, xnricens包
    8 G% ]' o9 }- R- D* N$ z6 s  i( K6 \#install.packages("nricens") # 安装R包  p7 t0 ~2 c% o  ?
    library(nricens), E6 V% Q/ x; z# c: w8 {( J
    1. K+ l% _! R6 @( Q3 b# T
    ## Loading required package: survival3 [( R4 F  J9 D: u0 p2 C
    13 H- p$ Q7 j; E/ t
    使用survival包中的pbc数据集用于演示,这是一份关于原发性硬化性胆管炎的数据,其实是一份用于生存分析的数据,是有时间变量的,但是这里我们用于演示logistic回归,只要不使用time这一列就可以了。
    : L! I. m; k) R) s3 v) X6 w. h" u6 t+ u& w( P/ g
    library(survival)/ P/ |5 C2 j- Z1 X

    : c- k# g  j2 s# 只使用部分数据& K( m  y  _) G" h
    dat = pbc[1:312,]
    9 |1 O+ n. B: r$ h. Hdat = dat[ dat$time > 2000 | (dat$time < 2000 & dat$status == 2), ]3 s6 D# l( r& @( [
      e% t) @) `( C2 a
    str(dat) # 数据长这样
    1 D. ]) {7 L, e( r- M1
    2 T# w+ A% C2 V+ {## 'data.frame': 232 obs. of  20 variables:! y6 ^% o! M. A6 o% k
    ##  $ id      : int  1 2 3 4 6 8 9 10 11 12 ...
    0 B; F2 y& ^: G  U  G/ f! r% G" R##  $ time    : int  400 4500 1012 1925 2503 2466 2400 51 3762 304 ...
    5 h0 l: S  Y0 T4 K0 q( ?3 [##  $ status  : int  2 0 2 2 2 2 2 2 2 2 ...
    # s; T  {0 P* f+ A6 ~( j' @##  $ trt     : int  1 1 1 1 2 2 1 2 2 2 ...' A7 k9 d# ]( K, y# H2 E
    ##  $ age     : num  58.8 56.4 70.1 54.7 66.3 ...
    : K; q4 S. @' K' x' e4 A4 m##  $ sex     : Factor w/ 2 levels "m","f": 2 2 1 2 2 2 2 2 2 2 ...  Y+ L7 t" D  A) ]2 c* l2 ^  i
    ##  $ ascites : int  1 0 0 0 0 0 0 1 0 0 ...5 g1 S, p, l! ~. Z& G) m% P' _6 A% U
    ##  $ hepato  : int  1 1 0 1 1 0 0 0 1 0 ...) t6 m; t/ s$ |7 n8 d8 B" r. z
    ##  $ spiders : int  1 1 0 1 0 0 1 1 1 1 ...
    3 @7 w1 S- c* ~##  $ edema   : num  1 0 0.5 0.5 0 0 0 1 0 0 ...
      ~, Q3 S: J8 Y! W( R  k##  $ bili    : num  14.5 1.1 1.4 1.8 0.8 0.3 3.2 12.6 1.4 3.6 ...7 k1 V4 G. J2 e. ]- k, b" ~
    ##  $ chol    : int  261 302 176 244 248 280 562 200 259 236 ...
    7 v1 X: ~% t$ h. P+ l##  $ albumin : num  2.6 4.14 3.48 2.54 3.98 4 3.08 2.74 4.16 3.52 ...- f6 b/ v9 `0 F. r# R; F$ \8 M2 O1 l
    ##  $ copper  : int  156 54 210 64 50 52 79 140 46 94 ...
    % Z6 S7 @' w( C$ H7 ?2 N( f##  $ alk.phos: num  1718 7395 516 6122 944 ...
    1 z5 e" I# u/ ^" v1 S' ?##  $ ast     : num  137.9 113.5 96.1 60.6 93 ...
    3 {3 a, X) B& s' |6 c- s. E& @. r##  $ trig    : int  172 88 55 92 63 189 88 143 79 95 ...
    . c5 ?5 R; _/ a: [+ c) D7 m##  $ platelet: int  190 221 151 183 NA 373 251 302 258 71 ...) w: }! V# U% j3 J
    ##  $ protime : num  12.2 10.6 12 10.3 11 11 11 11.5 12 13.6 ...
    4 X2 q( K( X1 Q1 |" z! `% T, D##  $ stage   : int  4 3 4 4 3 3 2 4 4 4 ..." }/ Y1 W' w, t0 Y" w: E  G/ q# b
    - ^2 k2 t+ z/ W( N
    1
    2 s0 H% A, P2 Kdim(dat) # 232 20
    % @2 l7 d) L6 Y0 K14 z6 b$ s9 H* M
    ## [1] 232  20
    ! x1 N8 z* G+ a% c/ v, O1' c1 W: F8 I4 j/ `
    然后就是准备计算NRI所需要的各个参数。: Y, g" E: \; M

    2 f% ?/ K* y* I8 n$ r# 定义结局事件,0是存活,1是死亡0 U1 r% N: e+ ?; n9 J9 [
    event = ifelse(dat$time < 2000 & dat$status == 2, 1, 0)2 J6 g; K) R5 Q1 Z

    2 _8 V) l2 i+ t! l0 r# 两个只由预测变量组成的矩阵
    $ u' t; X4 P, ~+ M" V) o# Tz.std = as.matrix(subset(dat, select = c(age, bili, albumin)))( z1 @5 f  p! r, Z2 d
    z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime))): i7 B/ d' s6 `4 \" G7 [

    8 q' a6 X$ X& E! t# 建立2个模型3 V6 m% E. y: |
    mstd = glm(event ~ age + bili + albumin, family = binomial(), data = dat, x=TRUE)6 \: S( v+ W* Q
    mnew = glm(event ~ age + bili + albumin + protime, family = binomial(), data = dat, x=TRUE)2 R  y! `4 v: F3 q2 J

    / b8 j+ P5 u$ O/ h) [# 取出模型预测概率0 u+ I, y( G3 F+ k
    p.std = mstd$fitted.values: d! ~3 x+ t; I  x; V3 D  ]
    p.new = mnew$fitted.values
    0 y) p! e. S; j+ L6 m! Z! v9 ]: h4 ^' Y$ e" X$ }
    1
    ( y/ V6 y: S- K& J然后就是计算NRI,对于二分类变量,使用nribin()函数,这个函数提供了3种参数使用组合,任选一种都可以计算出来(结果一样),以下3组参数任选1组即可。 mdl.std, mdl.new 或者 event, z.std, z.new 或者 event, p.std, p.new。8 N* L8 E7 V/ U+ T- M; G5 N

    / K! c! u4 U( M0 ]# 这3种方法算出来都是一样的结果
    $ X5 ?3 e) b/ V" v0 O2 v3 A0 L
    # 两个模型
    . I1 v9 [( ^- r4 N9 anribin(mdl.std = mstd, mdl.new = mnew, 0 g0 T- j9 O. p# ]+ C- U) l" G
           cut = c(0.3,0.7),
      U$ u8 h8 \$ u" C+ y       niter = 500,
    - ]8 w, ?! ^+ c" g: D# P& D& y  J       updown = 'category')( v1 S* C$ c+ W: P4 {

    # k: [8 B2 B' A3 Q( ?9 c9 y# 结果变量 + 两个只有预测变量的矩阵+ e: s& I  p) B4 n/ p
    nribin(event = event, z.std = z.std, z.new = z.new,
    # Z+ z7 G/ J: c       cut = c(0.3,0.7), * j, M+ Z2 J  }  Z9 z0 s+ S
           niter = 500,
    2 |2 ^  u/ G6 H( C4 ?* f: w       updown = 'category')7 O1 r# f6 l: y
      @2 A1 ~# N# H1 X+ Q# J: r
    ## 结果变量 + 两个模型得到的预测概率$ r* X1 o9 ~+ \9 b, l& I3 n! N5 p
    nribin(event = event, p.std = p.std, p.new = p.new,
    , c* O6 i6 u9 T. L6 C8 o$ o       cut = c(0.3,0.7),
    & R" Y4 r% |2 t% y       niter = 500,   U( H( D  j3 V- ^: z4 i# \
           updown = 'category')
    ) z" w9 F& c* z0 u' [9 O7 F& f  {! z6 J; K8 q+ g
    1, J* b4 S4 b6 h' u  {
    其中,cut是判断风险高低的阈值,我们使用了0.3,0.7,代表0-0.3是低风险,0.3-0.7是中风险,0.7-1是高风险,这个阈值是自己设置的,大家根据经验或者文献设置即可。
    ' g) |! l) W+ q1 A) P& W& P& w0 h
    / F0 v& V7 m3 C5 Q  H/ kniter是使用bootstrap法进行重抽样的次数,默认是1000,大家可以自己设置。, `0 s: i& O/ H. [1 Q" I1 D& ?/ A
    : x9 i) K, d. y  M
    updown参数,当设置为category时,表示低、中、高风险这种方式;当设置为diff时,此时cut的取值只能设置1个,比如设置0.2,即表示当新模型预测的风险和旧模型相差20%时,认为是重新分类。' `# K1 s* q' D: P2 l
    9 e' I: _3 k2 U1 c/ H
    上面的代码运行后结果是这样的:. I0 i6 S% H( f9 A

    / }* k' C  L2 _5 ~UP and DOWN calculation:
    % X, R% k/ P* L$ z6 h( Z1 S  #of total, case, and control subjects at t0:  232 88 144& k& E8 W- H$ a, t! c
    & z8 ?; j- f. P* D* H, u1 Q7 h4 {
      Reclassification Table for all subjects:
    3 @. L' Z" V& ~+ g0 a9 s; i; c2 T        New
    / j: \& k  b6 o8 H& IStandard < 0.3 < 0.7 >= 0.7
    , y# K) D9 d4 H, B3 h  < 0.3    135     4      0
    , c7 o/ |6 H" o9 a, @" [2 z* ]  < 0.7      1    31      4
    $ [4 y. ]' K$ [  >= 0.7     0     2     55' H2 d6 @; v4 c
    : N1 C# Q; k7 Z
      Reclassification Table for case:( ?# v/ B- W$ h1 M* `0 \3 ?
            New5 g$ E2 G& U( ]2 q& x
    Standard < 0.3 < 0.7 >= 0.7
    ( ^5 b0 p; @6 |$ ^: P  U# E0 O- D+ }  < 0.3     14     0      0
    0 r& @8 \- u' V: {1 O2 `! a6 R  < 0.7      0    18      3
    ! l! F, l5 w4 K# M! h  >= 0.7     0     1     52
    & b- C, ~( r8 }* W7 \' h
    / D9 {" R, k6 x5 h+ l5 g. f; U  Reclassification Table for control:( V% m% q" }) v' U
            New; {! Z1 r6 x3 c( E$ @# L; K
    Standard < 0.3 < 0.7 >= 0.77 [/ Q  p8 m( w% k- z
      < 0.3    121     4      05 y* V, R) h2 ?! F5 l. k/ m
      < 0.7      1    13      1
    # B: O8 m7 }, o; K. D# a! i  >= 0.7     0     1      3
    - Y$ P( B' P, h& [
    : i$ k7 G* }& V0 t& hNRI estimation:
    . \, q- P& F& t' m9 Z4 _8 h0 JPoint estimates:0 f! G5 y6 U: |  F6 `4 d. g
                      Estimate
    # L) z* G1 i( w) L$ qNRI            0.001893939
    . J7 t3 M. `& }1 ~/ U' ~- ^NRI+           0.022727273" ^3 W* w; `- M
    NRI-          -0.020833333
    ( H; ^, i/ C2 L+ o3 ^9 {Pr(Up|Case)    0.034090909$ y+ p% T% f$ Z$ V4 U8 N( i" W
    Pr(Down|Case)  0.011363636
    ( m" C1 A6 g/ |0 q- p  |Pr(Down|Ctrl)  0.0138888891 p: |3 h, b( M2 }+ B
    Pr(Up|Ctrl)    0.034722222
    5 J$ Y6 S; Q& D! v8 F1 v3 w3 t) A* K* p5 n
    Now in bootstrap..
    % B2 r  {  e! s8 p- N: H& n; M7 p) h/ U! o
    Point & Interval estimates:4 Y5 G) e% j) s! b* R3 y' \6 Z
                      Estimate   Std.Error        Lower       Upper
    8 j2 Z: v- q# _* oNRI            0.001893939 0.027816095 -0.053995513 0.055354449% L4 B: L/ M* T5 t* j$ A
    NRI+           0.022727273 0.021564394 -0.019801980 0.065789474
    5 @2 b9 d9 c2 Z# P7 u# DNRI-          -0.020833333 0.017312438 -0.058823529 0.007518797" H5 W+ F" u( @1 g" H8 e. N
    Pr(Up|Case)    0.034090909 0.019007629  0.000000000 0.072164948: W4 g$ ^9 T0 k; v) r
    Pr(Down|Case)  0.011363636 0.010924271  0.000000000 0.039603960$ `% b  V' M6 _4 S( u$ m& K
    Pr(Down|Ctrl)  0.013888889 0.009334685  0.000000000 0.035211268
    9 N* i% u* o5 K, QPr(Up|Ctrl)    0.034722222 0.014716046  0.006993007 0.066176471( ^) ]* t/ ^- ~! O
    9 x/ n1 {% V! X7 x
    1* J, M' Y+ k! `8 w5 u
    首先是3个混淆矩阵,第一个是全体的,第2个是case(结局为1)组的,第3个是control(结局为2)组的,有了这3个矩阵,我们可以自己计算净重分类指数。: \% W  M) |/ U0 L; p

    , c9 N+ |. \3 [# @. n: y- A- {看case组:
    ( O7 I: I& l) J0 O4 t% a, M$ Z% S" c+ T4 |6 n# s6 y
    净重分类指数 = ((0+3)-(0+1)) / 88 ≈ 0.022727273
    ( ]/ L' V% M' [
    % ^' V( A) G% }, w0 q/ n. e% T再看control组:
    * ^+ Y* T2 O# t' T4 H& F9 j, {: u9 \1 i8 `  f4 F  O  O
    净重分类指数 = ((1+1)-(4+1)) / 144 ≈ -0.020833333  C9 l5 `: U9 V* d; P5 L. k% D
    4 F- B0 u+ Z8 Q- L* w6 D
    相加净重分类指数 = case组净重分类指数 + control组净重分类指数 = 2/88 - 3/144 ≈ 0.000315657
    - l5 e, ]" E9 B4 j( L
    5 D7 Y- Q+ i7 N7 R* Q/ B5 J9 G再往下是不做bootstrap时得到的估计值,其中NRI就是绝对净重分类指数,NRI+是case组的净重分类指数,NRI-是control组的净重分类指数(和我们计算的一样哦),最后是做了500次bootstrap后得到的估计值,并且有标准误和可信区间。" ]* [* V7 z7 d" h& X. \% P$ [
    ( n4 W8 u# V7 h7 `
    最后还会得到一张图:) o, W, [  {% R0 Z: b$ V/ g% `
    ' v6 H1 m8 q+ v: R: T7 V
    这张图中的虚线对应的坐标,就是我们在cut中设置的阈值,这张图对应的是上面结果中的第一个混淆矩阵,反应的是总体的情况,case是结果为1的组,也就是发生结局的组,control是结果为0的组,也就是未发生结局的组。
    : \1 Q: `! X; E% k5 `- a
    0 m. P& {/ ?( |P值没有直接给出,但是可以自己计算。2 t2 k; S, r+ C, G2 @" D

      q* |8 q4 B5 c3 a1 }# 计算P值
    9 i1 q( a3 |% P- K- C; d$ k4 Yz <- abs(0.001893939/0.027816095)9 e. e# P/ c6 B$ r9 H$ I4 W4 l
    p <- (1 - pnorm(z))*26 j. h! y: C$ e4 y  F
    p
    + s$ S- r0 [. P1
    & s% i4 ]# ]/ r5 a) g4 `## [1] 0.9457157( t4 m5 M0 T& h# X3 d5 @
    1
    & L; ~$ l" e9 m9 |2 J8 ?5 OPredictABEL包2 B& P% u& c# S! J
    #install.packages("PredictABEL") #安装R包
    1 n; D# U' O, @, i  _7 mlibrary(PredictABEL)  $ `3 i0 W; W/ y; K

    * V0 }& C* d' P; j! {# 取出模型预测概率,这个包只能用预测概率计算
    ( \5 D* T. d" {p.std = mstd$fitted.values
    ! ]3 G% G+ i/ B( Hp.new = mnew$fitted.values
    : X+ |) Z9 [! ~  |0 z1
    , w' h/ R, W2 m/ G* k. Z* c然后就是计算NRI:
    4 E  w; c+ h4 [8 J
    # z8 I8 ^- G- a/ Vdat$event <- event) {, N7 ?" X4 N- A5 t

    8 t3 C! H) ^1 Y" d# p+ ?reclassification(data = dat,$ J/ |; q- m1 b7 `4 E
                     cOutcome = 21, # 结果变量在哪一列
    * t' ^8 h# A0 S                 predrisk1 = p.std,
    ' N( K. r; q7 y4 P                 predrisk2 = p.new,
    + [9 b" e1 p) [4 T. V- O                 cutoff = c(0,0.3,0.7,1)8 W5 p- b+ p; J7 k: j( `
                     )
    7 j# r  @. j2 \! b0 H3 w1
    3 Q/ J( X+ q3 {5 G% D# U4 d##  _________________________________________1 f1 L2 O+ N/ y
    ##  
    & v6 t2 v& i! W. y##      Reclassification table   
    " y1 p1 j" M& ~; G# H( c+ N##  _________________________________________
    ; d6 r4 M2 ^. @+ Q7 `! ~## * L0 @8 d( W! g' _) @
    ##  Outcome: absent 3 R& ^$ ^* z  N5 k! G& ?$ r
    ##   9 z& P/ E+ I3 O: ~6 ^. {9 y1 H
    ##              Updated Model- G- |6 A$ h9 Y7 {
    ## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified; F4 D. l+ z: B' l
    ##     [0,0.3)       121         4       0               3
    & R* j  R" f4 I##     [0.3,0.7)       1        13       1              13
    * p# {1 {% ?# r0 {3 o+ N8 j' p##     [0.7,1]         0         1       3              25. h; E6 G; Y! z( ?) j2 C
    ##
    # C! {% X- x4 m5 K4 t6 G  t##  
    4 n7 a% F5 {! l0 {3 Z. \4 ~' a, q/ E" t##  Outcome: present + Q+ C" K. g8 A" o/ p- q" u$ t
    ##   3 v6 r7 {# \& C, V/ p
    ##              Updated Model
    2 d0 [% z5 P& W& a## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified8 s: m: X. ?$ L9 B) _
    ##     [0,0.3)        14         0       0               09 l4 n0 c( W" G2 m
    ##     [0.3,0.7)       0        18       3              14+ Z8 d$ R6 J+ W/ b0 f5 F& a9 M3 ]$ r
    ##     [0.7,1]         0         1      52               20 X! O' `3 X+ B4 t, m' V: E3 V
    ## . C% g1 Z3 k3 Q9 p" l2 K* M3 }! ]8 I
    ##  9 m7 Y. V7 }) A: M# O( ?0 U
    ##  Combined Data - {! t! e$ O. ^- A2 ^0 m5 M
    ##   6 j; ]0 p1 r  {" t
    ##              Updated Model  U& O0 X2 O: n  n
    ## Initial Model [0,0.3) [0.3,0.7) [0.7,1]  % reclassified) Z- i5 j! F( ^
    ##     [0,0.3)       135         4       0               3
    $ p+ J- s9 k$ a- ?, a* Y##     [0.3,0.7)       1        31       4              14
    * \  h4 ~4 P- A3 j9 v* N##     [0.7,1]         0         2      55               4
    ' d& D3 f( m0 a##  _________________________________________/ `1 \: n) r3 R9 _& a
    ##
    & g5 {* H1 g0 z9 z##  NRI(Categorical) [95% CI]: 0.0019 [ -0.0551 - 0.0589 ] ; p-value: 0.94806 + N$ a$ p4 y/ @( I
    ##  NRI(Continuous) [95% CI]: 0.0391 [ -0.2238 - 0.3021 ] ; p-value: 0.77048
    / i8 \( _7 P, N: f& I2 G##  IDI [95% CI]: 0.0044 [ -0.0037 - 0.0126 ] ; p-value: 0.28396
    7 i  U9 F- |1 f( g9 D1 l, Z$ A: U9 \
    2 f  k! c! l+ `3 V5 D" U1
    - m( I' @3 Y0 {4 W3 b4 g; K结果得到的是相加净重分类指数,还给出了IDI和P值。两个包算是各有优劣吧,大家可以自由选择。9 j3 m; T* T# u; i+ t
    " E3 _5 j/ w$ d: M/ w
    生存分析的NRI
    # C# Z& [. E8 g5 @还是使用survival包中的pbc数据集用于演示,这次要构建cox回归模型,因此我们要使用time这一列了。! x* a# r5 ^+ Z% ^  R; s  T) l
    ' D9 S! G3 U' n! D9 ~( e
    nricens包
    " Q7 Q1 P3 B3 c% W- ]; A1 x  |" ]" h$ wlibrary(nricens)
    0 V/ G1 K$ Y3 ]" L* plibrary(survival)
    - ?" T3 \" E& l; e+ u) @9 `% i5 X/ }1 D( ?% B! ]' {7 z& ], r
    dat <- pbc[1:312,]
    ! V* P8 x+ y7 c! Tdat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡
    $ W. s& a% O4 ]8 W1
    ; T0 y7 u5 \5 q; a( a然后准备所需参数:+ o# E' Y/ L! n$ o' k% a7 `; z
    & S& T+ q. H: J5 ^' @) a  u
    # 两个只由预测变量组成的矩阵  B! u" ~; T' M: z
    z.std = as.matrix(subset(dat, select = c(age, bili, albumin)))% F$ X# r1 m, m1 v
    z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime)))
    , {6 i' _6 @! o* v! b5 y. B; V$ t
    # 建立2个cox模型2 a/ n3 V9 o7 M. w0 L; D9 l
    mstd <- coxph(Surv(time,status) ~ age + bili + albumin, data = dat, x=TRUE)4 x5 o  W( U. B5 ?( V3 Y( r- r& G9 u
    mnew <- coxph(Surv(time,status) ~ age + bili + albumin + protime, data = dat, x=TRUE)
    ! M6 U, m0 w3 o/ y* L  c
    % \! Z+ y$ z+ X6 ?# 计算在2000天的模型预测概率,这一步不要也行,看你使用哪些参数
    * o, |7 c! J4 Y9 ~p.std <- get.risk.coxph(mstd, t0=2000). g/ O. a2 z- P3 |$ A/ P; S- e
    p.new <- get.risk.coxph(mnew, t0=2000)
    % S4 J6 b6 ]- A0 C1 [1
    . _1 Q- P2 X) ~2 H计算NRI:
    8 P, Q3 ^5 U" o$ t6 g+ C1 M# p9 z/ ]7 d" x( o7 a9 X
    nricens(mdl.std= mstd, mdl.new = mnew, ' d+ t, q4 `9 l( ?7 Q/ A7 T
            t0 = 2000, 7 K9 s( q: T: }8 i. d' U
            cut = c(0.3, 0.7),+ D/ A! ~4 K0 X1 L0 C2 Q
            niter = 1000,
    , k9 g2 W- c% i0 T/ h9 r7 v        updown = 'category')
    * \& a2 B7 S3 N- Z% w6 |4 s- |( f0 G, c' m5 P
    UP and DOWN calculation:5 F6 }1 u& b5 B
      #of total, case, and control subjects at t0:  312 88 1448 X( k7 V, [+ ~. q4 T: x8 M9 R+ p
    ' B6 E) o  ]$ }+ R
      Reclassification Table for all subjects:) @# [& Q7 i5 V
            New
    4 z$ E" S; |0 c1 X/ o8 }/ W. tStandard < 0.3 < 0.7 >= 0.7
    6 ^* o- ^% H) f, q" _; u  < 0.3    202     7      0
    + ?4 c8 r/ U( k0 D  < 0.7     13    53      6; x( D7 ~4 V& M- R+ C5 W6 v
      >= 0.7     0     0     310 n5 g: Y  G+ C! s& n2 t# f; b
    - U/ r) m: l( `
      Reclassification Table for case:
    # B7 {4 |$ H  Z# A- `4 @! D) n9 ~        New& d6 S/ _4 a  A; k' F0 _
    Standard < 0.3 < 0.7 >= 0.74 f$ b5 j/ m( |  i
      < 0.3     19     3      0& S4 N, i( L! s5 Z5 U
      < 0.7      3    32      4
      z+ c0 M- h9 ^( I  >= 0.7     0     0     27* k' b& n% i+ g) i, V, ]
    ) d- r8 X* W7 ^6 F) X% I9 O8 n
      Reclassification Table for control:1 |+ w& f# S; a' ^! I! F5 v( a
            New
    ; v- t. Q. z1 G* f+ P  PStandard < 0.3 < 0.7 >= 0.7
    $ {: s1 w- U1 n. M, t  < 0.3    126     3      02 _% X( m, @, I/ y& P
      < 0.7      5     7      2
    4 S4 q  G. A+ A9 c0 U! L; W& e+ D" |  >= 0.7     0     0      1( ~. s5 s( ^4 ]3 W
    $ H; o# \: Z- ]
    NRI estimation by KM estimator:
    # T# ], c* B  Z# Q) Y+ q! a& N) K7 J" }: Q9 S
    Point estimates:
    5 @* H6 r0 ^/ D7 c                Estimate
    ! T" j) ?4 r8 @NRI           0.05377635
    9 z6 v4 y' i/ a4 x/ jNRI+          0.03748660
    - K2 V# {$ r4 q- u' X' T. XNRI-          0.01628974# l+ x* L; J0 ~, D# o6 p
    Pr(Up|Case)   0.077089382 z- E, D* O/ W# C& U! ?7 B
    Pr(Down|Case) 0.03960278' z# v' y; O. ^$ m' V1 P
    Pr(Down|Ctrl) 0.04256352
    3 ~* Q$ T$ Y5 [! q0 N, t9 z1 o) E4 X2 iPr(Up|Ctrl)   0.02627378* I3 h: H/ q# _
    # v1 m  ^& c6 k: S( R: G
    Now in bootstrap..& i6 t6 q, L% W' H2 k

    8 u/ Z' l- u/ ?4 H* A1 fPoint & Interval estimates:: z$ I% C& P# i: ]# q1 B( ^5 R
                    Estimate        Lower      Upper
    4 d1 x. i# p2 S) rNRI           0.05377635 -0.082230381 0.16058172
    . u9 z  ?' _7 Y; l; E5 ]" G8 _2 _NRI+          0.03748660 -0.084245197 0.13231776* W2 l; m0 L; `) }5 r
    NRI-          0.01628974 -0.030861213 0.06753616
    0 P. o. `) E5 p. J7 S# CPr(Up|Case)   0.07708938  0.000000000 0.19102291
    * b8 J- Y: O4 {0 k' i3 i/ c, H+ \Pr(Down|Case) 0.03960278  0.000000000 0.152360160 f' |9 h! m/ e" q, O$ F
    Pr(Down|Ctrl) 0.04256352  0.004671535 0.09863170) @  r# G; M/ W/ P
    Pr(Up|Ctrl)   0.02627378  0.006400463 0.05998424* T- W' b7 e- r  z) v1 v# B% s
    8 C+ j4 B2 M2 l; o: e
    1
    * P; h7 r7 {2 U8 e/ h+ ]
    7 d  r: c+ K3 q1 n: ySnipaste_2022-05-20_21-49-38
    " i7 }' T: X( |5 v结果的解读和logistic的一模一样。7 M( v- Y* Y) k' U
    7 }  H0 p/ J+ Y8 u- n; a1 s6 H
    survNRI包
    + l$ o. H3 J& y  Q2 j, c) R# 安装R包+ P- Q% t# I2 Y. ?0 d
    devtools::install_github("mdbrown/survNRI")
      @$ R! f3 i  Q/ G9 ]17 |$ s, ]4 |- u! q3 N, W1 ~
    加载R包并使用,还是用上面的pbc数据集。% a, b. m+ l8 ?7 J

    5 @/ y, K5 a4 Z8 a) `library(survNRI)7 l6 `7 _6 O) U# R
    1' a' T! O$ q; ?% V" Z3 a
    ## Loading required package: MASS8 M+ g" {  p" n( e7 }" Y" Q/ ~& y$ m
    1
    1 B0 h% Y& `6 O" n" `library(survival)
    : ^. s. |! o+ z- K3 E/ Q
    1 d4 P7 P$ G9 A) R  T. U3 ]( l# 使用部分数据8 k9 x8 B% U  b3 N& Y. a! R* d# P; x
    dat <- pbc[1:312,]
    , j; V" C) F6 V! pdat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡  K8 W1 |9 n* f, x5 S
    6 I2 I' L: a) L! W  O5 z; r! m
    res <- survNRI(time  = "time", event = "status", 1 Y+ ~$ D( x4 b: K5 I$ E" c
            model1 = c("age", "bili", "albumin"), # 模型1的自变量
    ' B5 R7 E. Q& M9 E  }! t        model2 = c("age", "bili", "albumin", "protime"), # 模型2的自变量' p+ {- h( P( A' U, j7 \1 D
            data = dat, 4 G! A# J. I- ~2 B. _
            predict.time = 2000, # 预测的时间点
    ( W. c# k, C$ F$ H4 ?        method = "all",
    . v% a2 r0 v1 }3 k/ V# n        bootMethod = "normal",  
    3 Y/ Y, Y) D- Y7 \4 O+ @3 \9 t        bootstraps = 500, 3 ^+ `* P# y4 q+ h
            alpha = .05)! S, l  _9 a6 e. X& h( S
    + g1 `5 {* }/ B* |$ Y) Y5 b& u
    1# a1 |9 C7 k6 h
    查看结果,$estimates给出了不同组的NRI以及总的NRI,包括了使用不同方法(KM/IPW/SmoothIPW/SEM/Combined)得到的结果;$CI给出了可信区间。
    8 s; H/ b7 e/ [7 j: {* u0 d  A
    6 |% k) \% Q; d3 Qres5 B; Z* V! F. B
    1
    : C  M: m; a3 A## $estimates
    ! F2 I. E4 K; ]& H. \/ _6 K##            NRI.event NRI.nonevent       NRI
    % K; W5 J5 n3 I5 M! v: @0 a## KM        0.20445422    0.3187408 0.5231951
    9 K# p/ z, q8 b7 S1 g7 E0 x## IPW       0.22424434    0.3273544 0.5515987
    # W8 n) L" p$ @) T, Y+ y0 r! G" }## SmoothIPW 0.19645006    0.3144263 0.5108763
    / S  M, S7 ^6 I, T$ s## SEM       0.07478611    0.2632127 0.3379988% Y- ?% n9 H; o% E* @; {
    ## Combined  0.19633867    0.3143794 0.5107181
    : ?4 V8 g8 ]$ d4 K3 X## % V. Q/ _& \7 Z( z
    ## $CI' y- a0 e8 _  ~8 G5 Q% j
    ## $CI$NRI.event& Y% [. F5 D7 `  B. ?$ d
    ##                     KM         IPW   SmoothIPW        SEM   Combined
    7 C6 F* F( W- O* Y8 s## lowerbound -0.03915924 -0.02185068 -0.04724202 -0.1162587 -0.0473723
    . ^- h6 u7 ~6 u' e+ L) q% g' n## upperbound  0.44806768  0.47033936  0.44014214  0.2658309  0.4400496
    ' K* a4 ~5 V) m& F##
    % G  ^* F3 N% t+ p7 W* m. a2 \## $CI$NRI.nonevent' B8 [; v1 b& l3 |- z0 f
    ##                   KM       IPW SmoothIPW        SEM  Combined) s: m! s, i+ q2 Z# H
    ## lowerbound 0.1317108 0.1396315 0.1286685 0.08638933 0.1286426: L( q0 E, h8 ]0 L8 V2 g
    ## upperbound 0.7102251 0.7393216 0.6966341 0.51482212 0.6964549
    9 v0 m4 p+ o5 s6 V## " U) K  L3 ~: ]! s2 ^* ?
    ## $CI$NRI
    ) {. n* z% {8 k4 @( M$ `##                     KM         IPW   SmoothIPW         SEM    Combined% S& \- N- N) Q1 k2 n
    ## lowerbound -0.05112533 -0.04569046 -0.05439863 -0.04132364 -0.05443409
    + Q* A& n8 ?( H5 F( A' A## upperbound  0.89306122  0.92464359  0.87970125  0.64253510  0.879531536 R( t% x. w8 U7 l6 T
    ##
    + @. S$ i. @# K* P## ) Q) m1 c0 j) Y, r+ C
    ## $bootMethod) P! C, h1 e/ \% Z
    ## [1] "normal"
    . g. u* {# G# f2 t##   Y2 ^) a& V1 Z% k+ k6 O1 |
    ## $predict.time
    / M  k; p# i: A' s& P, V## [1] 2000$ ~2 }, H* S2 |, |" u+ [
    ## - [3 A- n, l. f/ ^" R( v& z
    ## $alpha
    - N* s0 G* w" q## [1] 0.05
    , d6 z& e6 r% x& J7 }##
    - {2 p% P( M* o## attr(,"class")
    / f0 @) f9 A" K& k* L- g' b## [1] "survNRI": p. s" c' v5 i3 R3 A( M
    . ^  a! p2 N: p  ^0 k
    1
    9 a- H4 z$ n5 i& T$ rOK,这就是NRI的计算,除此之外,随机森林、决策树、lasso回归、SVM等,这些模型,都是可以计算的NRI的,后面会继续介绍。大家如果有问题欢迎在评论区留言。9 ~. D% p7 V8 y% M+ v8 u

    8 U6 U& ]. Y% P! J+ k0 F% p本文首发于公众号:医学和生信笔记* T9 N7 j8 I! f& k6 j
      e" F( O7 Q* V1 o
    “ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。
    - r+ j8 h6 Q, l* t0 W* i, n! F本文由 mdnice 多平台发布; P" v4 i8 v: p
    ————————————————* z: B9 ~3 T2 D" ~
    版权声明:本文为CSDN博主「阿越就是我」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。* {+ Y0 V3 O. O
    原文链接:https://blog.csdn.net/Ayue0616/article/details/126768006* Q) n) |+ S7 e5 P  o

    0 p, y- d& h) m' T) T- h# ]5 D( B0 Q: i5 H% f1 Q' h3 E
    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, 2025-7-29 01:39 , Processed in 0.685656 second(s), 51 queries .

    回顶部