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