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