数学建模社区-数学中国
标题:
净重新分类指数NRI的计算
[打印本页]
作者:
杨利霞
时间:
2022-9-12 18:43
标题:
净重新分类指数NRI的计算
% v, E, L, U: }+ ]3 t# h
净重新分类指数NRI的计算
6 k7 r9 t7 X, t- G
“ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。
8 \3 k! f8 i/ A$ W9 _8 ~
NRI,net reclassification index,净重新分类指数,是用来比较模型准确度的,这个概念有点难理解,但是非常重要,在临床研究中非常常见,是评价模型的一大利器!
$ q/ c [) U) C
" i- `, C ]- Z0 F
在R语言中有很多包可以计算NRI,但是能同时计算logistic回归和cox回归的只有nricens包,PredictABEL可以计算logistic模型的净重分类指数,survNRI可以计算cox模型的净重分类指数。
4 H6 y: l% g/ }& s
: s6 V: @3 o. `1 A; y" v: d7 `3 ?
logistic的NRI
4 q$ m( R9 w! Q ^' d
nricens包
c, ]" R* `! @. V
PredictABEL包
m; S/ }) R6 E X
生存分析的NRI
' M* N! W2 c, }& y" D- x7 h
nricens包
! |9 u0 U5 v; c9 w0 S
survNRI包
3 m7 X& \( H9 |6 h, J
logistic的NRI
. g5 O8 d9 T; ^" I2 X- t5 Q
nricens包
. J" ? b' P' k2 c
#install.packages("nricens") # 安装R包
$ Y1 v5 B: E5 O* M) l4 c
library(nricens)
# n6 o0 m; h' G' c* \
1
$ J, P1 l- G& b$ V
## Loading required package: survival
) C: N$ W4 V# v; M! j
1
6 y% ]- k5 l: m4 P* w
使用survival包中的pbc数据集用于演示,这是一份关于原发性硬化性胆管炎的数据,其实是一份用于生存分析的数据,是有时间变量的,但是这里我们用于演示logistic回归,只要不使用time这一列就可以了。
! A, U" P. h; m4 [, B5 p9 v5 a
% y( s, N3 W$ ]( Q8 U1 s
library(survival)
7 p. F; s2 v; U2 b
$ U9 t3 x% h: M( F, ^$ T
# 只使用部分数据
$ r$ ?) v6 _1 I$ c% z$ _1 z: U
dat = pbc[1:312,]
& V+ A. m1 |5 M
dat = dat[ dat$time > 2000 | (dat$time < 2000 & dat$status == 2), ]
$ w1 ~1 k% u& b/ O |) m. _
- D2 Z3 e, C/ Y% b
str(dat) # 数据长这样
; n) E7 t% n) W; A* n
1
u7 i) q0 @/ `0 y
## 'data.frame': 232 obs. of 20 variables:
5 p0 o, s k# c% s/ U
## $ id : int 1 2 3 4 6 8 9 10 11 12 ...
9 k5 i& b; p6 g2 N9 t! g5 Z; x! [
## $ time : int 400 4500 1012 1925 2503 2466 2400 51 3762 304 ...
+ P y5 J1 Z! r
## $ status : int 2 0 2 2 2 2 2 2 2 2 ...
9 n9 L2 c% w( B+ l: i
## $ trt : int 1 1 1 1 2 2 1 2 2 2 ...
9 F8 _0 D$ u; s2 n
## $ age : num 58.8 56.4 70.1 54.7 66.3 ...
& q* f- h. D+ P/ r C. ~+ V
## $ sex : Factor w/ 2 levels "m","f": 2 2 1 2 2 2 2 2 2 2 ...
: E5 D0 H/ Y1 I5 d
## $ ascites : int 1 0 0 0 0 0 0 1 0 0 ...
4 H. D5 O& W0 }% u( E# c% a
## $ hepato : int 1 1 0 1 1 0 0 0 1 0 ...
5 d1 C3 D9 z! s+ X# R D$ s
## $ spiders : int 1 1 0 1 0 0 1 1 1 1 ...
4 t- J) X- E7 x8 u
## $ edema : num 1 0 0.5 0.5 0 0 0 1 0 0 ...
+ w. j6 m, @' u+ |; g! y. W6 D
## $ bili : num 14.5 1.1 1.4 1.8 0.8 0.3 3.2 12.6 1.4 3.6 ...
) S' n/ r' ^0 ^3 \
## $ chol : int 261 302 176 244 248 280 562 200 259 236 ...
i) l0 k, ~* v. e# J" P
## $ albumin : num 2.6 4.14 3.48 2.54 3.98 4 3.08 2.74 4.16 3.52 ...
- F) w* q1 b1 ^/ w. R9 X9 z
## $ copper : int 156 54 210 64 50 52 79 140 46 94 ...
( v4 r& r5 k( G0 N8 U
## $ alk.phos: num 1718 7395 516 6122 944 ...
: ?6 x7 N& R" V" y, A m+ b
## $ ast : num 137.9 113.5 96.1 60.6 93 ...
4 v# [ T4 G |1 T, s
## $ trig : int 172 88 55 92 63 189 88 143 79 95 ...
% h, Q. z$ K6 G' i' M" A2 g
## $ platelet: int 190 221 151 183 NA 373 251 302 258 71 ...
/ s# f% u0 W9 l2 H) J
## $ protime : num 12.2 10.6 12 10.3 11 11 11 11.5 12 13.6 ...
9 q5 I! n) V( _" Z0 p- G
## $ stage : int 4 3 4 4 3 3 2 4 4 4 ...
7 s5 o% V5 |5 ~3 F; t
- y$ [7 E- C4 S; b# b
1
; o/ {( i- z6 g. I; G8 r
dim(dat) # 232 20
; z4 r% W. `3 L$ t6 Y( P+ V% \4 U
1
- W y2 L6 R* p% J8 e
## [1] 232 20
" Z. Q; g3 M( m" T1 G0 M" W4 c
1
2 Q) D4 G5 G5 p: n
然后就是准备计算NRI所需要的各个参数。
6 {) K4 h& Y# Q
) G. G& v' Y2 k* J
# 定义结局事件,0是存活,1是死亡
5 }$ U) w9 p% A# G1 X( \
event = ifelse(dat$time < 2000 & dat$status == 2, 1, 0)
- R; N. o; o2 O4 P" v% n* |! k9 I; \+ f
' S. i1 _3 C7 O( X
# 两个只由预测变量组成的矩阵
8 c, L$ C1 O O
z.std = as.matrix(subset(dat, select = c(age, bili, albumin)))
/ Z k. }! q: j- G4 C
z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime)))
' F+ J/ Q; n( w1 T. |- D
" i8 m \& N' Y% M8 `. Q
# 建立2个模型
* p2 o3 C/ j& ^5 D, N7 W. ~
mstd = glm(event ~ age + bili + albumin, family = binomial(), data = dat, x=TRUE)
# c! G+ @& x- m7 i
mnew = glm(event ~ age + bili + albumin + protime, family = binomial(), data = dat, x=TRUE)
5 ]7 w& E& y# q9 C+ ?& v0 Z
+ c M7 [* B7 c: e
# 取出模型预测概率
% a5 i, C$ }3 X K8 t
p.std = mstd$fitted.values
! b8 f3 ~, w% ?
p.new = mnew$fitted.values
3 H& ?: n5 y; f7 U1 G. u( j4 |1 D k
6 s; P7 T+ W$ W5 r9 |
1
# t5 e: a1 ^ ]7 A$ }( Z
然后就是计算NRI,对于二分类变量,使用nribin()函数,这个函数提供了3种参数使用组合,任选一种都可以计算出来(结果一样),以下3组参数任选1组即可。 mdl.std, mdl.new 或者 event, z.std, z.new 或者 event, p.std, p.new。
5 E z7 x' {( S, z; t8 b$ {
2 e5 T9 y' x1 I% n- |8 S- l, c
# 这3种方法算出来都是一样的结果
5 D( S# l6 E4 t2 `3 a4 H: O+ y* F% ^
. }, A) ?' t) }3 o6 A. Q9 \
# 两个模型
4 Z( g% c& Z5 X" @
nribin(mdl.std = mstd, mdl.new = mnew,
e2 A; W/ N: ~( k
cut = c(0.3,0.7),
7 {$ f1 D y2 r2 M; ?
niter = 500,
# e) o/ } S: O2 A
updown = 'category')
9 }/ _' t9 M: g% }3 G' g- M1 R9 P6 t
: ^* W! b7 v1 ^0 ^) |
# 结果变量 + 两个只有预测变量的矩阵
2 i& {- B$ p5 {; d( k( @
nribin(event = event, z.std = z.std, z.new = z.new,
N" e) l3 \6 s
cut = c(0.3,0.7),
7 `7 c5 T; ]+ f/ b: z
niter = 500,
6 ^ y5 c0 b- Q5 |: l
updown = 'category')
. Q1 F/ P& v8 Q& ` h
- p) d6 p- k& h2 d- m7 W/ `
## 结果变量 + 两个模型得到的预测概率
7 u1 O8 R1 d/ i, X5 b
nribin(event = event, p.std = p.std, p.new = p.new,
% R6 ? S7 h. v8 C$ {! l
cut = c(0.3,0.7),
1 X. ^9 C' z7 E% `" f: _
niter = 500,
: X) E: u Z) T; [, i1 Q! j
updown = 'category')
% y0 {4 K! B$ K( h; l
. a0 T; u |; @5 X$ p/ s
1
9 k3 {: |1 m% ~% m Y, s- g
其中,cut是判断风险高低的阈值,我们使用了0.3,0.7,代表0-0.3是低风险,0.3-0.7是中风险,0.7-1是高风险,这个阈值是自己设置的,大家根据经验或者文献设置即可。
+ {! b: U1 z2 t
( o; L) j- n( X
niter是使用bootstrap法进行重抽样的次数,默认是1000,大家可以自己设置。
6 U Q1 w( h) O
1 l+ o: X2 E" [9 d. {% T8 {/ z8 |3 ^
updown参数,当设置为category时,表示低、中、高风险这种方式;当设置为diff时,此时cut的取值只能设置1个,比如设置0.2,即表示当新模型预测的风险和旧模型相差20%时,认为是重新分类。
' J5 E; f8 W4 D; f" N& Q/ X8 a
' |" p7 d; P3 t2 P! K
上面的代码运行后结果是这样的:
- J5 X: K2 i$ Y; X) [1 ?
+ A7 i+ {( q. I
UP and DOWN calculation:
+ ]- B& b5 v* p \: c- `
#of total, case, and control subjects at t0: 232 88 144
) |8 \9 J+ f5 E) G0 h1 Z
! ~" C2 V# T0 z2 ^
Reclassification Table for all subjects:
5 v8 }5 z0 l, J- @! H, i
New
% N$ w7 A. _' c8 a" T! Y9 ], e6 }0 B
Standard < 0.3 < 0.7 >= 0.7
6 @' Z; O, U* a! ?
< 0.3 135 4 0
7 q1 Z- y3 Y% K& N0 x& X0 f
< 0.7 1 31 4
0 }6 g1 J, u* b% Z }
>= 0.7 0 2 55
2 }: e' @( V. j: M J
9 a2 N2 M5 D9 @) c h
Reclassification Table for case:
% [0 N/ o% e9 r6 `# e9 t* x
New
4 g, d. H: C7 q6 }# m+ M8 S
Standard < 0.3 < 0.7 >= 0.7
& P2 o' @- |3 C
< 0.3 14 0 0
8 \' J) K7 I9 j/ M7 F
< 0.7 0 18 3
) \: \' G% f, |0 i5 F+ d
>= 0.7 0 1 52
" Z* {& Q- f( F
: \; V6 a: ?) y1 w, [
Reclassification Table for control:
9 A) A$ g, K/ @8 V2 T
New
7 _' q0 H, m8 M$ f) b8 |
Standard < 0.3 < 0.7 >= 0.7
: g1 r9 s0 }4 h8 T* z
< 0.3 121 4 0
, g& w3 ]% \1 u4 D$ P. v
< 0.7 1 13 1
" C9 O# ^& H6 W
>= 0.7 0 1 3
) Q2 ~ Y" b# A2 z) e( x3 y4 V4 l- f
2 b1 @, \' {3 ~& C- m: H/ L4 m4 i
NRI estimation:
6 L, e& m+ b/ j9 C: C
Point estimates:
; V; `( Y, G/ J
Estimate
0 R& F7 M# J4 H8 Q6 S1 ?5 ^
NRI 0.001893939
) D8 P/ [% R! }5 q g
NRI+ 0.022727273
6 A) `4 |: y( X% a4 M/ ^% S/ k
NRI- -0.020833333
3 \' n4 o7 e) } O* }
Pr(Up|Case) 0.034090909
+ N$ }- k& w$ r7 n5 r/ [4 m
Pr(Down|Case) 0.011363636
) g$ ~3 F3 j9 c: [' R9 G; m
Pr(Down|Ctrl) 0.013888889
9 ?- C R5 D2 w$ ~2 Y; D1 S
Pr(Up|Ctrl) 0.034722222
) x7 e, i0 a( I& l* h
' U4 x9 t @4 x
Now in bootstrap..
! H" t; x1 S' @, H
" u e, X( K- [- \1 a
Point & Interval estimates:
6 E8 f+ u( a/ ^" q1 e- V
Estimate Std.Error Lower Upper
0 D: m5 H1 A. p: k; a7 ]- z
NRI 0.001893939 0.027816095 -0.053995513 0.055354449
* t0 m( q' D6 k, M% k8 j
NRI+ 0.022727273 0.021564394 -0.019801980 0.065789474
: T9 E! Z/ \6 |3 Z/ [
NRI- -0.020833333 0.017312438 -0.058823529 0.007518797
( s$ W U# ?& l& _+ g+ f5 }" X
Pr(Up|Case) 0.034090909 0.019007629 0.000000000 0.072164948
3 r8 [5 |$ Q; U/ e/ E1 y7 K' B4 g1 _
Pr(Down|Case) 0.011363636 0.010924271 0.000000000 0.039603960
: t! g. H- N- s" o P# {* O4 _2 k
Pr(Down|Ctrl) 0.013888889 0.009334685 0.000000000 0.035211268
. e! `* G6 e. r( r
Pr(Up|Ctrl) 0.034722222 0.014716046 0.006993007 0.066176471
$ N' D. [' F# Q, p* n- A* F6 A; j
" {, F5 @8 J$ ]" Z- `+ w2 o' M
1
7 x9 g1 n: E5 W1 D8 @
首先是3个混淆矩阵,第一个是全体的,第2个是case(结局为1)组的,第3个是control(结局为2)组的,有了这3个矩阵,我们可以自己计算净重分类指数。
, v. f1 B7 I, P- F& K7 _
9 N& s0 f0 c% T% W/ a
看case组:
% }0 ?+ |7 F' Z5 { u+ y
8 p2 C% F) g& @" u( B
净重分类指数 = ((0+3)-(0+1)) / 88 ≈ 0.022727273
, I8 y* U( ~8 ?) _3 t
/ P+ W" @( ^& ?; [' `, Y6 _8 @
再看control组:
4 Q! m. X; x. x
4 f% Z" t3 L# z
净重分类指数 = ((1+1)-(4+1)) / 144 ≈ -0.020833333
2 X2 j5 O7 p; K0 S3 `; C) g
" T, _3 { H1 @7 _5 Y3 Z* ?
相加净重分类指数 = case组净重分类指数 + control组净重分类指数 = 2/88 - 3/144 ≈ 0.000315657
& }8 n4 [& Z% N& r
4 l0 J$ m) N* Z% h; h7 L6 ~$ B# \
再往下是不做bootstrap时得到的估计值,其中NRI就是绝对净重分类指数,NRI+是case组的净重分类指数,NRI-是control组的净重分类指数(和我们计算的一样哦),最后是做了500次bootstrap后得到的估计值,并且有标准误和可信区间。
" \2 B R- [/ V/ a- Q
$ L. z/ t, M Q
最后还会得到一张图:
4 R( P0 H* D+ |
+ Z: K* @1 u! N2 ?/ R
这张图中的虚线对应的坐标,就是我们在cut中设置的阈值,这张图对应的是上面结果中的第一个混淆矩阵,反应的是总体的情况,case是结果为1的组,也就是发生结局的组,control是结果为0的组,也就是未发生结局的组。
" v) ~% {- Y5 H
0 k7 \8 R7 F) u! k6 H3 k# N
P值没有直接给出,但是可以自己计算。
, Y) w0 R# e U# x8 U2 C
, o$ u4 b% u" l9 _' l7 y& P. @8 |
# 计算P值
8 R4 k c* w' g4 i0 x8 J/ R
z <- abs(0.001893939/0.027816095)
c o1 R2 L' _) G& a1 m
p <- (1 - pnorm(z))*2
# ~9 O* ^6 ^3 o: d
p
, C& {% T- Y+ }+ _" @
1
1 O3 e& ^# [ f2 N( ]: G
## [1] 0.9457157
$ |3 M# o# i1 H) V7 O F2 q
1
+ p+ O, @: _1 I) R; ^" Y
PredictABEL包
0 R5 {: y5 |% F; F' P x Q
#install.packages("PredictABEL") #安装R包
8 t3 [4 E d8 O& C. W9 u
library(PredictABEL)
1 V+ J0 b8 G$ h7 B5 U
$ ] C$ U) P- D7 u: v
# 取出模型预测概率,这个包只能用预测概率计算
2 P. m% i7 E6 Z0 @5 ?9 \: ~% j0 ^$ q
p.std = mstd$fitted.values
9 G ?% ?, ^3 E
p.new = mnew$fitted.values
g1 ]( u' c* Q6 x% c& ~& V
1
% y' Z5 h, l' [& \$ e1 m% b5 q% w5 R
然后就是计算NRI:
5 ~" U5 h$ }7 y- g/ R
4 w: {7 X- U+ B
dat$event <- event
+ I6 A7 B% A2 ]+ `
+ U) A6 s* F6 v8 }# s
reclassification(data = dat,
; N& [2 c9 F6 x; v8 F
cOutcome = 21, # 结果变量在哪一列
0 p5 S8 T$ O+ b I$ z
predrisk1 = p.std,
4 p" z1 ]1 |% }$ t7 h" v( y+ r
predrisk2 = p.new,
4 L& p6 C- A K2 C0 f; o* S# ]
cutoff = c(0,0.3,0.7,1)
8 h5 M4 O q0 T5 d0 ^1 d2 ^( C1 x4 _; k
)
% n! P0 b/ G) f' V) P
1
; {5 M, l. K2 f4 E& C5 h9 {
## _________________________________________
4 s- h2 m z! h' Y
##
9 Z. ` e( X5 w9 ^ s1 @
## Reclassification table
8 y: G. \6 w4 L, [5 \% K
## _________________________________________
3 Y# i7 N; J6 P5 }5 ?3 H5 J
##
5 I _# J; O V* U7 ]* P3 W3 N% t
## Outcome: absent
z0 S% N4 t+ G$ E
##
( d6 M) H9 y8 n. D
## Updated Model
! z7 L. w' S4 `0 k+ c0 `% u1 g
## Initial Model [0,0.3) [0.3,0.7) [0.7,1] % reclassified
+ M& Q/ J% E& z# Z: N3 }3 b0 X
## [0,0.3) 121 4 0 3
" w7 h/ L; `( }: }& J5 j6 D9 d. k$ Q
## [0.3,0.7) 1 13 1 13
: G8 k3 I% \/ l+ Q- l3 I5 g/ v% m! C
## [0.7,1] 0 1 3 25
4 `/ Z! ?" D/ O0 Z
##
& M1 c7 |# j7 X+ t/ r% `- S& q
##
6 z8 W9 m' Z) [, u( f
## Outcome: present
1 i9 Z9 Y, ~& F6 `
##
# [7 [' a* D' {. S
## Updated Model
* P0 W# m* P6 [; r. `1 b( J
## Initial Model [0,0.3) [0.3,0.7) [0.7,1] % reclassified
4 C, `2 Z/ S' k9 j/ n
## [0,0.3) 14 0 0 0
% l n! [/ J2 s9 d
## [0.3,0.7) 0 18 3 14
# p2 C" d3 E9 }# I. w
## [0.7,1] 0 1 52 2
; D2 y0 V' t$ f: E: s8 f
##
5 W m# d- W/ h8 @7 [+ u
##
# M L0 N& `. D. [, j. }
## Combined Data
1 T9 ]$ K6 w. z* l' d7 ~
##
% t G4 P! l+ p _4 s% [# @
## Updated Model
+ q) ^. Y% S( i, g$ g; r( D' ^4 z4 ?3 c
## Initial Model [0,0.3) [0.3,0.7) [0.7,1] % reclassified
6 O- n3 {7 }* t$ M5 T, ]- t$ u
## [0,0.3) 135 4 0 3
. D: N5 t; D" Y
## [0.3,0.7) 1 31 4 14
7 P$ P! p, Q2 ?# \0 e9 ^; V! s
## [0.7,1] 0 2 55 4
! |7 b3 {: y* k
## _________________________________________
4 j2 O* c6 y/ s. z
##
+ |1 o+ C1 S% _+ U2 D: t' Y
## NRI(Categorical) [95% CI]: 0.0019 [ -0.0551 - 0.0589 ] ; p-value: 0.94806
. [5 ~" L; M! i+ ]0 E, X+ U1 \
## NRI(Continuous) [95% CI]: 0.0391 [ -0.2238 - 0.3021 ] ; p-value: 0.77048
5 Q L+ |/ o' R
## IDI [95% CI]: 0.0044 [ -0.0037 - 0.0126 ] ; p-value: 0.28396
5 a+ p& Y0 Z- l$ m4 J+ i6 h+ k
. @4 ^( e5 P$ O* o3 S* B
1
' u) S: |0 r! L2 |# w! e
结果得到的是相加净重分类指数,还给出了IDI和P值。两个包算是各有优劣吧,大家可以自由选择。
! H. [. v2 g. D& @2 @; j; P8 ^
7 C! j% T7 P. d1 z- p0 d) H5 p. w
生存分析的NRI
, i: K2 ^& t7 }" {0 D; A$ ]7 N* R! S$ b
还是使用survival包中的pbc数据集用于演示,这次要构建cox回归模型,因此我们要使用time这一列了。
" q/ o" S; ~ F8 b' e8 X2 y: q
: p7 R- g; f ]% I
nricens包
: C- C0 n! T8 ^4 O, S3 R
library(nricens)
5 n- i* p T5 H; D
library(survival)
# d; x" p! w. ]3 ^& x' N
6 O+ `9 K$ w% u
dat <- pbc[1:312,]
' M' N1 q2 B" [
dat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡
# \, f* I6 S4 G# p& B2 ^4 v+ Z
1
+ O/ l7 @& J) L% V
然后准备所需参数:
; [& m/ U! \4 H; S& R5 M# X
$ i: f3 {/ n1 ~5 |& V% G
# 两个只由预测变量组成的矩阵
, v8 w0 w1 f0 T' T# L) b8 Z
z.std = as.matrix(subset(dat, select = c(age, bili, albumin)))
4 e5 `7 R: l4 K' D
z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime)))
) @) h1 ~. G( _# q
" D5 Y; F% a+ Y
# 建立2个cox模型
; y, ^2 o! L: }" A7 Z" x
mstd <- coxph(Surv(time,status) ~ age + bili + albumin, data = dat, x=TRUE)
f8 o; r1 `. m3 C
mnew <- coxph(Surv(time,status) ~ age + bili + albumin + protime, data = dat, x=TRUE)
" X/ C/ y# Q9 J9 r/ r. b
/ f9 o# [+ E* |
# 计算在2000天的模型预测概率,这一步不要也行,看你使用哪些参数
/ L4 I D3 e% w, m2 I
p.std <- get.risk.coxph(mstd, t0=2000)
, a8 ~4 g, F5 _: h5 G1 t' e4 u/ w
p.new <- get.risk.coxph(mnew, t0=2000)
$ [$ N' v4 R# `6 e8 V" r9 |0 a
1
+ _8 J$ o# T- g/ A8 j# m
计算NRI:
. C. C: \) r3 r9 V7 F
! K. w: N- a: q' ]4 t
nricens(mdl.std= mstd, mdl.new = mnew,
1 c' H: p F) W6 }& [
t0 = 2000,
; C% c) K- n0 @! y! \: Y9 Y
cut = c(0.3, 0.7),
! d6 }5 o$ F. r2 z
niter = 1000,
6 Y; Q* u* S) a7 N3 k( n
updown = 'category')
- N9 f3 ^& S% O% H. \" R
: n# q0 R* r6 o
UP and DOWN calculation:
7 s6 F' w! A) W5 J
#of total, case, and control subjects at t0: 312 88 144
) D: d3 Z7 T6 m$ ^9 f0 x
0 @2 D& A8 V- @7 J! j
Reclassification Table for all subjects:
! L$ X$ [; A: R0 l- S
New
( w& m' L A: i
Standard < 0.3 < 0.7 >= 0.7
6 J8 c6 H6 G( Z5 m: f* J z5 g
< 0.3 202 7 0
0 r- N# ^6 i4 H9 s) f9 b8 h
< 0.7 13 53 6
$ H+ M. g9 d) {2 V1 C9 Y
>= 0.7 0 0 31
+ Z- o9 A/ \! u
5 L5 k8 [7 u( F7 O; T3 a
Reclassification Table for case:
# d- C$ o7 r! H% o! {2 i1 r
New
/ W; c9 _9 x) j& L
Standard < 0.3 < 0.7 >= 0.7
- [& o- m$ a! |: R
< 0.3 19 3 0
# Q$ G3 B" h7 o+ Z6 |% Q0 t
< 0.7 3 32 4
' R U( {, J" N
>= 0.7 0 0 27
0 M1 e" C" ]$ [, Z- w
+ ?5 A/ g4 Y9 T
Reclassification Table for control:
; M: V& r. Z1 v. ^
New
" k( F" C9 b T5 @9 t4 K
Standard < 0.3 < 0.7 >= 0.7
1 E2 s9 p+ f4 S
< 0.3 126 3 0
8 i- A0 t) W- ^2 I8 E
< 0.7 5 7 2
. { Z7 N# I! A. c8 o1 y8 e- U% G2 t& E
>= 0.7 0 0 1
$ _! S$ N4 l% m7 P/ A( J
; O8 Z X9 z, ~2 ~
NRI estimation by KM estimator:
$ l! H/ X( K* W& u( u9 P% @7 i
$ L4 e3 Q% \3 I& S
Point estimates:
{. X6 s/ H0 d
Estimate
2 W& {1 P( w. p2 U6 v
NRI 0.05377635
0 k; x5 N( F5 v+ D8 X
NRI+ 0.03748660
" V3 u+ L5 s8 d- I5 C
NRI- 0.01628974
+ Z2 d0 }! l2 Z8 x! E+ ]2 l8 h3 q( h
Pr(Up|Case) 0.07708938
8 j; x# `% j& I7 r+ g. N9 M
Pr(Down|Case) 0.03960278
& E8 U% R! w8 i2 Q5 e6 l. K2 T* N
Pr(Down|Ctrl) 0.04256352
' i9 m+ g. P; g; W4 q
Pr(Up|Ctrl) 0.02627378
" U! Q$ s9 ]6 I& m3 y9 s2 p% ^" x6 b
! k _* Y/ N7 a4 S, Q: R+ I* X
Now in bootstrap..
- U) G! H) |* w! X# E
' P' n+ \+ e' V8 \
Point & Interval estimates:
" U: W/ p/ b0 f: ` x4 C5 q
Estimate Lower Upper
' p' I6 m1 v, p6 @/ j
NRI 0.05377635 -0.082230381 0.16058172
2 X* A4 u k1 U* d0 S6 B. D6 \' r
NRI+ 0.03748660 -0.084245197 0.13231776
2 G* f$ _' i0 _1 Y( V& O
NRI- 0.01628974 -0.030861213 0.06753616
5 q* T5 Y& _' d% q( R
Pr(Up|Case) 0.07708938 0.000000000 0.19102291
. N V/ T9 ~, F# e6 K9 N2 C) ~
Pr(Down|Case) 0.03960278 0.000000000 0.15236016
" i+ D2 \8 s1 N$ ]9 t3 z
Pr(Down|Ctrl) 0.04256352 0.004671535 0.09863170
2 t8 B b" y* _% C: b
Pr(Up|Ctrl) 0.02627378 0.006400463 0.05998424
, E" _+ B( _/ Q! L! N
6 H: P& X, m! ]1 S, h& p( n
1
" J2 Y3 T2 _1 z9 a5 X
* P% ]1 E( a2 k- D2 ?' v
Snipaste_2022-05-20_21-49-38
! N+ I, h0 l% i6 \8 A
结果的解读和logistic的一模一样。
2 r# K" \1 @* \% x/ i1 v% ]( f
) I. p& Q( y }, ?/ C% \
survNRI包
8 z, z7 i$ S1 n# d) y* ^" h
# 安装R包
" ]% J7 s; X1 e" O9 E
devtools::install_github("mdbrown/survNRI")
" f s! ^8 R, f/ S
1
( T5 A' R7 g0 w% R1 M' |2 y1 V( J
加载R包并使用,还是用上面的pbc数据集。
2 B6 e/ A- _3 G0 {& K/ X
/ N8 D' }% f% L
library(survNRI)
$ B$ d( _3 e1 C r. i, N1 B
1
( m3 i4 E7 s. r* P. T
## Loading required package: MASS
0 ^, I4 L! G2 y" U
1
5 Z4 W2 I% e1 v1 N- x0 ]) i
library(survival)
9 ~- w3 h: f% M% R
4 D- ]9 Z1 _9 I$ @" F
# 使用部分数据
3 G3 Z6 P# T' D$ C6 u7 P% I
dat <- pbc[1:312,]
% j' ~5 l# k* Y. |# g7 Z
dat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡
0 P/ {, s7 j. `$ p+ \
" n3 ^& @7 ^. H6 C v' z
res <- survNRI(time = "time", event = "status",
2 X: i0 M; A! R
model1 = c("age", "bili", "albumin"), # 模型1的自变量
, R! ^* R* B, |1 }/ G9 C
model2 = c("age", "bili", "albumin", "protime"), # 模型2的自变量
J, `+ l, L- C" _* f8 N! q; E& g
data = dat,
+ e( }3 O7 F" Z& w6 B
predict.time = 2000, # 预测的时间点
. @( q" V0 d& T2 C/ q/ ?
method = "all",
) k, u$ \7 f" i" b& J) k# b
bootMethod = "normal",
6 R$ k1 m4 H( Y/ t
bootstraps = 500,
& y+ R4 I4 n; A9 b
alpha = .05)
, ^, m! A6 _+ h; f/ @
; F+ d- s! P" B8 n% {1 @
1
! [5 q7 t$ ]9 ~9 k
查看结果,$estimates给出了不同组的NRI以及总的NRI,包括了使用不同方法(KM/IPW/SmoothIPW/SEM/Combined)得到的结果;$CI给出了可信区间。
6 d4 d% b H$ V0 Q$ P/ P \- s/ |
& l3 U! {4 J; ?; T$ q& I: F
res
0 m" { ~" s+ {& M/ c
1
+ \: k: ^& r1 e
## $estimates
5 l) p& a* j. U2 b. g5 ]
## NRI.event NRI.nonevent NRI
1 B% ~' b6 i& `
## KM 0.20445422 0.3187408 0.5231951
9 }9 R" O, \& j
## IPW 0.22424434 0.3273544 0.5515987
0 m& Q% S8 H7 t0 y9 F
## SmoothIPW 0.19645006 0.3144263 0.5108763
& I2 R$ C$ ~0 j; F0 g
## SEM 0.07478611 0.2632127 0.3379988
/ H0 t; S. [& z4 V" P9 S
## Combined 0.19633867 0.3143794 0.5107181
% b- T; l9 o. N v
##
$ |; K# v6 ^4 U
## $CI
7 }) ?" O ], n& P5 \
## $CI$NRI.event
5 k7 _$ Y+ I* A/ |' c" b, o
## KM IPW SmoothIPW SEM Combined
) d: o; m2 S- e9 S+ K; |# w: R* w
## lowerbound -0.03915924 -0.02185068 -0.04724202 -0.1162587 -0.0473723
# G/ d) K1 N: z8 |' `4 W
## upperbound 0.44806768 0.47033936 0.44014214 0.2658309 0.4400496
7 @- ^, ]5 ?) @3 h) C9 y4 C3 [
##
X4 {9 ^; l1 F& p+ m! o
## $CI$NRI.nonevent
4 P! w( s; u" `% i; F
## KM IPW SmoothIPW SEM Combined
/ K' |+ {& g& v' H$ E0 r! E
## lowerbound 0.1317108 0.1396315 0.1286685 0.08638933 0.1286426
4 W7 X g. ]9 f1 K4 G
## upperbound 0.7102251 0.7393216 0.6966341 0.51482212 0.6964549
$ M/ Y" E w* l2 _# a
##
) d" O4 d2 r' }9 P& a/ G
## $CI$NRI
. @6 e6 l/ D7 t! R# \0 q u" b1 J1 \4 W
## KM IPW SmoothIPW SEM Combined
- j7 \( t, r. Y$ ] I/ u/ p" L$ y
## lowerbound -0.05112533 -0.04569046 -0.05439863 -0.04132364 -0.05443409
1 I! o% l$ f) V* w, K
## upperbound 0.89306122 0.92464359 0.87970125 0.64253510 0.87953153
6 V; a% H2 |9 m+ b
##
$ `" n6 Z1 Y- X0 Z! ]1 D
##
0 q" _1 n, B+ b
## $bootMethod
. R0 O0 c; p" [: E. a
## [1] "normal"
* v5 x+ d y" t
##
; W% Z6 M( C' H1 w. Y
## $predict.time
, v( T; y2 V, @
## [1] 2000
; E' C# C; q8 S( T* B. F7 [5 f# k
##
' Z/ u$ k# \" o" R9 K1 h8 @& z( L
## $alpha
4 ?; ]! T( p4 {/ P3 [4 t
## [1] 0.05
7 ^2 @/ u7 l2 M# z/ S3 _4 l% \
##
3 y" G: t+ V8 [$ u
## attr(,"class")
/ Z( c, S# J8 e5 |/ Q1 q
## [1] "survNRI"
# [. C( {" g; g( D- i" N Q
4 C% c$ e( i1 Q# D- h: M
1
# h6 N( p* l2 h7 O1 }- j$ O- z$ [
OK,这就是NRI的计算,除此之外,随机森林、决策树、lasso回归、SVM等,这些模型,都是可以计算的NRI的,后面会继续介绍。大家如果有问题欢迎在评论区留言。
# R0 n( N3 C5 R* B
|4 {6 T2 ]+ Z+ f, l. E& f! ]
本文首发于公众号:医学和生信笔记
1 y+ O+ r7 ^& r7 k; y/ K8 Y
. r) T( P( p8 b3 g
“ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。
o( t- n: k q3 C" }5 I
本文由 mdnice 多平台发布
; V0 s. D. l' {* |& w) T/ ^
————————————————
@9 P0 S, _1 \7 j
版权声明:本文为CSDN博主「阿越就是我」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
/ N7 C e( E) C( e! u# M8 X
原文链接:https://blog.csdn.net/Ayue0616/article/details/126768006
! K$ v- o# b% }9 I" h5 f
) a' i1 c+ g( q
6 o$ ]! C. M% l x8 p; W
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5