在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 563252 点 威望 12 点 阅读权限 255 积分 174198 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 3 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
3 n1 H* c% M) H
净重新分类指数NRI的计算
# m- w# Y. x/ d& d8 ?- F5 O% q9 V5 a “ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。) G0 M A7 F. f
NRI,net reclassification index,净重新分类指数,是用来比较模型准确度的,这个概念有点难理解,但是非常重要,在临床研究中非常常见,是评价模型的一大利器!1 w* B$ l6 z! X) U! v3 q0 t& V1 M0 c
1 ^; p/ z/ @7 P+ t# ]' o* F+ u: W
在R语言中有很多包可以计算NRI,但是能同时计算logistic回归和cox回归的只有nricens包,PredictABEL可以计算logistic模型的净重分类指数,survNRI可以计算cox模型的净重分类指数。
* w6 N' V9 u' t" b
! I. X/ U" b; U/ W, {8 F, s logistic的NRI9 Y& u/ a, j3 r( s
nricens包
, E6 S; y7 b! r) [5 a PredictABEL包2 R r2 }- P# W' h4 `+ c+ B" [0 Z* a
生存分析的NRI" E/ \/ J; E2 w
nricens包; J" P; l9 E& j1 L2 P. L8 R8 r( D
survNRI包
4 K7 U3 ~+ Y# v" l0 l4 O: T, t& b logistic的NRI" h7 v* t0 V3 P" O
nricens包
( S5 l3 B, k1 L+ u0 R$ T/ L, x #install.packages("nricens") # 安装R包
7 l+ l, l2 }# e$ j/ @ library(nricens)
% @: g! o4 c! `) g4 B 1) m/ g+ n2 P# |/ B3 D( Z; A, P
## Loading required package: survival
C* R' G# r3 y+ d$ Q) ]0 i J7 U6 A 1
, \3 b& n8 r* h8 d% }- m+ x 使用survival包中的pbc数据集用于演示,这是一份关于原发性硬化性胆管炎的数据,其实是一份用于生存分析的数据,是有时间变量的,但是这里我们用于演示logistic回归,只要不使用time这一列就可以了。! C6 s, d! {& _2 e
! Y9 q5 F9 c- v5 Q; E- T
library(survival)
; ?9 {; C; a. v9 S( p: M / [0 f9 D. m; o, C/ {3 D
# 只使用部分数据
2 L4 E" Y" w1 T% H: H- ] q dat = pbc[1:312,] : U# S0 @/ h9 F- T/ l) s6 k: o
dat = dat[ dat$time > 2000 | (dat$time < 2000 & dat$status == 2), ]3 Q# k; ^% K5 K% O4 J) H! E" z7 R
1 e/ ` s1 a- j( | str(dat) # 数据长这样
. |3 k2 ]$ r% _" s- f% w( g1 v 1* A5 z# T' j" a, w& u$ h$ S+ O. o9 y5 a
## 'data.frame': 232 obs. of 20 variables:
( v1 ]3 T8 L) |# ~; h/ }" \ ## $ id : int 1 2 3 4 6 8 9 10 11 12 ...7 O7 S3 Y) z5 Q/ C
## $ time : int 400 4500 1012 1925 2503 2466 2400 51 3762 304 ...
9 r7 ]/ B3 M# ~8 H ## $ status : int 2 0 2 2 2 2 2 2 2 2 ...3 v# O Q/ J# H) f' f8 R/ g
## $ trt : int 1 1 1 1 2 2 1 2 2 2 ...& L% X# u2 u' H$ ]
## $ age : num 58.8 56.4 70.1 54.7 66.3 ...
) n" ]2 q" i6 Q2 y M ## $ sex : Factor w/ 2 levels "m","f": 2 2 1 2 2 2 2 2 2 2 ...3 G& [( G7 v7 n5 P( K: D8 [
## $ ascites : int 1 0 0 0 0 0 0 1 0 0 ...2 u, g6 O% H0 A' @
## $ hepato : int 1 1 0 1 1 0 0 0 1 0 ...
9 e1 A1 N, k9 W6 @, ~/ W, X+ s! z0 _ ## $ spiders : int 1 1 0 1 0 0 1 1 1 1 ...
" U6 N7 c( R3 C( f1 I9 d' x ## $ edema : num 1 0 0.5 0.5 0 0 0 1 0 0 ...
2 N) Y% i2 [9 x7 c ## $ bili : num 14.5 1.1 1.4 1.8 0.8 0.3 3.2 12.6 1.4 3.6 ...
. t/ l- s5 R( v& Q ## $ chol : int 261 302 176 244 248 280 562 200 259 236 ...( E/ g g( F9 w
## $ albumin : num 2.6 4.14 3.48 2.54 3.98 4 3.08 2.74 4.16 3.52 ...
/ ^. z! e3 i: C' E# | ## $ copper : int 156 54 210 64 50 52 79 140 46 94 ...5 A: R# e# A7 @5 y' p* h
## $ alk.phos: num 1718 7395 516 6122 944 ...& Z0 C# o& e* H
## $ ast : num 137.9 113.5 96.1 60.6 93 ...
+ {# Q" x( [8 S* ~% |, |: k ## $ trig : int 172 88 55 92 63 189 88 143 79 95 ...
# e- \# a" U$ m1 y: ~. s ## $ platelet: int 190 221 151 183 NA 373 251 302 258 71 ...
5 t# Y4 ~' j6 w ## $ protime : num 12.2 10.6 12 10.3 11 11 11 11.5 12 13.6 ...$ i) Y- F2 u3 E. ]- m4 x( i# G
## $ stage : int 4 3 4 4 3 3 2 4 4 4 ...
+ \/ Q# q! P+ t( N! U
5 g: T) X6 m/ R+ S2 B 1: N& l; q9 M7 _) t8 J
dim(dat) # 232 209 R6 u \" A1 b" P& U) Q: ^+ q
1
& h8 |+ W# Z7 t0 b4 q ## [1] 232 202 K+ o6 C. A! ~' b1 O" @1 h
1
+ @$ A" d, u/ c8 R$ q0 l 然后就是准备计算NRI所需要的各个参数。! I& D1 e0 D! [' `' \7 J
' Y' P9 `3 i7 W& ~
# 定义结局事件,0是存活,1是死亡
. }) K; I5 ~5 P event = ifelse(dat$time < 2000 & dat$status == 2, 1, 0)
" M3 v; E7 P0 B1 y
$ h' L& f7 k6 C # 两个只由预测变量组成的矩阵4 {7 A- C8 r8 {/ E* J9 n
z.std = as.matrix(subset(dat, select = c(age, bili, albumin)))
/ T/ O/ k& Q7 Y% g z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime)))
+ C2 c( |6 `1 w+ E3 E
: `. \. P1 z! k2 t# f, j # 建立2个模型
3 \# l6 B0 g3 E+ t0 z# w* H mstd = glm(event ~ age + bili + albumin, family = binomial(), data = dat, x=TRUE)
, n9 b( l1 F( l6 L5 [4 p mnew = glm(event ~ age + bili + albumin + protime, family = binomial(), data = dat, x=TRUE)
, j* f+ y. y. K! ^2 r# j. n, G0 ~
2 E/ a# N; Z: m% k; O7 ^7 } # 取出模型预测概率% k/ A/ i& ]" w2 Y- R9 @7 A' Y1 }
p.std = mstd$fitted.values
3 G* |( a: q8 o; ?" T p.new = mnew$fitted.values
" @9 O* G' i# x9 \/ K! e5 Q
5 }. N) Q$ F/ ?+ `& F 1$ D! X/ o- X+ I0 F/ Q( Q+ t( d
然后就是计算NRI,对于二分类变量,使用nribin()函数,这个函数提供了3种参数使用组合,任选一种都可以计算出来(结果一样),以下3组参数任选1组即可。 mdl.std, mdl.new 或者 event, z.std, z.new 或者 event, p.std, p.new。" M8 }2 k" s4 s/ E
* `, G C9 k+ @6 t7 j6 `; `$ g # 这3种方法算出来都是一样的结果
% Z0 T R3 d) Y' O3 [5 c* r 6 @1 |3 J* Y8 i9 M5 |
# 两个模型
. d% J* W2 t5 ?- t2 v nribin(mdl.std = mstd, mdl.new = mnew,
: @6 {8 [( d9 L cut = c(0.3,0.7),
/ Q3 e& _; {8 Q: b( k+ G. A niter = 500,
8 C( t+ _4 `6 \ updown = 'category')
0 I, e. q8 @- _* e 7 @, x/ g& h- b" r+ ~
# 结果变量 + 两个只有预测变量的矩阵; _* s$ v- d6 ^! z; R
nribin(event = event, z.std = z.std, z.new = z.new,
& W0 V7 }. M; `; y1 D+ v cut = c(0.3,0.7),
8 R" f( U: O' w$ Q6 I niter = 500,
! y2 p2 W/ Z/ S! l3 T/ z updown = 'category')
+ a' i1 t+ H# I5 w7 B% V
8 O2 L2 |" A3 Y- o3 R; G ## 结果变量 + 两个模型得到的预测概率% [6 x" J) Y% N0 F! z
nribin(event = event, p.std = p.std, p.new = p.new,
: q/ e, M8 R" K: G1 b cut = c(0.3,0.7), $ [) r9 f N1 a* Q
niter = 500, 0 |+ X4 J: Y+ B( I6 ^9 K, |) ]
updown = 'category')
& D& r- z- O" Z5 o ; S' A1 P ^$ v1 _" {
1
9 b+ s% A4 {. w' W4 ^/ g {3 ~% U 其中,cut是判断风险高低的阈值,我们使用了0.3,0.7,代表0-0.3是低风险,0.3-0.7是中风险,0.7-1是高风险,这个阈值是自己设置的,大家根据经验或者文献设置即可。
& l, d G! ~% H9 A
- K+ ]3 `. a6 [9 _4 x8 C% { niter是使用bootstrap法进行重抽样的次数,默认是1000,大家可以自己设置。8 z& g" |& B# t
0 }/ q& K' t9 Q+ o7 Y3 y5 d0 E updown参数,当设置为category时,表示低、中、高风险这种方式;当设置为diff时,此时cut的取值只能设置1个,比如设置0.2,即表示当新模型预测的风险和旧模型相差20%时,认为是重新分类。
, b7 d, G2 Q j8 Q , c4 g N; U3 }: e! ]2 p M
上面的代码运行后结果是这样的:) K( o7 V G: z1 |
! r4 W# J( p/ r
UP and DOWN calculation:
2 Y2 M# l2 a9 E4 o" P/ M! r! e #of total, case, and control subjects at t0: 232 88 144& ]. v% e, C) @! i4 D; Q
3 h9 V5 B3 N- W, |% P) b% i Reclassification Table for all subjects:
( v# A* a% F7 I0 ~ New
: W3 R; I- Q! Q3 q0 r9 ?- @! t! _ Standard < 0.3 < 0.7 >= 0.7. n% i: W8 S5 b2 ~2 I6 j
< 0.3 135 4 0
6 [: E- T a# F8 | < 0.7 1 31 4
; N: ], \% t+ \) t9 I# P >= 0.7 0 2 55
4 S( X; A3 m' m$ x' _
- s- d3 w/ `; @4 B' z) a' J Reclassification Table for case:& A& V' k* m* V! n! ]: u7 ?% k8 c
New( N) r! o( G) {' e1 p
Standard < 0.3 < 0.7 >= 0.7
- Z* Y/ d8 O7 S8 z6 H < 0.3 14 0 0- j. f( @5 B* T* I0 U" L9 H4 A) f
< 0.7 0 18 3; Q( T2 J# e: H, H* B0 `0 ~
>= 0.7 0 1 52
, g, y1 H# z% l z
" ^4 [! q K! n/ ^ Reclassification Table for control:# [5 h( c ^( e4 ~/ R) W9 y$ ~
New
/ n" V/ z; c% Q* k. k; k Standard < 0.3 < 0.7 >= 0.7
; T* [/ o3 @, G < 0.3 121 4 0
( O( D( ]$ B$ P$ U0 z: _ < 0.7 1 13 1 R( r% w+ `, T
>= 0.7 0 1 3
4 u2 ?/ M; u R ; A' ~+ ~" [3 i6 ^
NRI estimation:/ v w; d9 B# y% |4 C, {, l
Point estimates:
* p9 J4 b& f0 r, X Estimate& w; v) Y+ Q _ m
NRI 0.001893939
% R4 u2 q- U" D) k, m% u3 \. u NRI+ 0.022727273( X) \% P3 c2 f6 C1 ?! T ~
NRI- -0.0208333337 J) B. c' V' @' H" C5 c
Pr(Up|Case) 0.0340909096 v7 Q+ w4 G; b$ v% ~
Pr(Down|Case) 0.0113636367 Q, ~* `# e/ ~
Pr(Down|Ctrl) 0.013888889
1 g) Q& l* E3 ]3 ?5 { Pr(Up|Ctrl) 0.0347222222 d1 l8 T8 L2 V; ^0 r) b
5 e) E; l( R( w# |; A& C8 W. p- h
Now in bootstrap..
0 Z- I# U: D2 X2 O! L( \
' J. _! E& I6 i- C; O+ P Point & Interval estimates:
' z4 Q y0 h! c+ Y. ]5 _! L5 n. T Estimate Std.Error Lower Upper, U/ }7 N% u) ~7 D1 s% R+ Z! U
NRI 0.001893939 0.027816095 -0.053995513 0.055354449
) s w3 r: |- _0 A NRI+ 0.022727273 0.021564394 -0.019801980 0.065789474& M; r) P# l6 x6 d: u6 L# z, n# O9 m
NRI- -0.020833333 0.017312438 -0.058823529 0.007518797
, P* ^/ i" n$ ? t: \ Pr(Up|Case) 0.034090909 0.019007629 0.000000000 0.072164948
1 z9 l+ l. n% W( G4 c' Q Pr(Down|Case) 0.011363636 0.010924271 0.000000000 0.039603960 W0 o7 ]/ t/ K7 F) |4 W. f9 g
Pr(Down|Ctrl) 0.013888889 0.009334685 0.000000000 0.035211268# c: h6 ?: x1 d# `. f/ W& Y
Pr(Up|Ctrl) 0.034722222 0.014716046 0.006993007 0.0661764717 X4 e7 M( j' m
3 E: T, G# F q 1; L- G# L; ~* V) I. o4 H9 K/ F
首先是3个混淆矩阵,第一个是全体的,第2个是case(结局为1)组的,第3个是control(结局为2)组的,有了这3个矩阵,我们可以自己计算净重分类指数。4 [: c3 J+ _! X. H2 B& E
9 @ b! {" X$ t2 |. z 看case组:& G( {0 n4 S6 |% q8 \7 S- H
4 c) k& a! i, R5 } 净重分类指数 = ((0+3)-(0+1)) / 88 ≈ 0.022727273
1 X0 C; P' O% a 0 Z* R1 ~0 ^1 R# U
再看control组: u1 j7 p1 t. l! `
3 F# R/ z7 v6 k
净重分类指数 = ((1+1)-(4+1)) / 144 ≈ -0.020833333' C- @( W7 m, x7 E" Q7 e7 q
0 @' R6 ?4 F$ a 相加净重分类指数 = case组净重分类指数 + control组净重分类指数 = 2/88 - 3/144 ≈ 0.0003156576 _' K) m: k% f% n* C" a0 |5 r- J
" p, Y- k1 t+ ]! E0 h4 J6 I0 Q9 N2 L. y 再往下是不做bootstrap时得到的估计值,其中NRI就是绝对净重分类指数,NRI+是case组的净重分类指数,NRI-是control组的净重分类指数(和我们计算的一样哦),最后是做了500次bootstrap后得到的估计值,并且有标准误和可信区间。) r0 q! O& W6 b/ q4 [$ o
: K9 m4 d" {4 i
最后还会得到一张图:, p" t% O. |- e+ E& h- _
9 M1 t% ~4 _( M7 p" b. @
这张图中的虚线对应的坐标,就是我们在cut中设置的阈值,这张图对应的是上面结果中的第一个混淆矩阵,反应的是总体的情况,case是结果为1的组,也就是发生结局的组,control是结果为0的组,也就是未发生结局的组。
. a# R+ m4 `' l* X7 { / J, s2 Y' ~ ^; h. l2 [
P值没有直接给出,但是可以自己计算。 \. H6 w3 {) d/ O$ q5 C0 D- T
/ z! j/ T: [, e3 ~9 F% P* _ F # 计算P值3 y, y0 G0 o/ S9 U, J
z <- abs(0.001893939/0.027816095)
' o ^; l" i, K# b5 G% `" u p <- (1 - pnorm(z))*2
" {% C# ]" Y( \ z Z$ F. C p$ L, N, H' x: X
1
( K" E: u; R5 K! ~' D+ b ## [1] 0.9457157
' k" E- Q, j8 @- y7 ~9 U2 ]0 z 1/ T4 I3 m5 A; O3 P: Z5 J/ `
PredictABEL包
/ {) d/ d/ b0 O2 ~8 E #install.packages("PredictABEL") #安装R包9 U" v2 ?4 I# [. C- U. W. _2 x2 R5 n
library(PredictABEL)
+ R0 c# z3 n4 ?: Z$ M" ~
5 I- i, x6 r) K# f4 }* `0 g # 取出模型预测概率,这个包只能用预测概率计算5 a% I6 ?2 @1 H5 S
p.std = mstd$fitted.values
6 r B4 L+ V/ C/ w+ F p.new = mnew$fitted.values % I" B+ z8 Z3 g( B8 d8 g( }6 g9 t
1
1 |' [2 Y9 ]: A% K+ t: j d$ \ 然后就是计算NRI:
* g1 A9 e' J: p) N u
" R" u% {( T0 j7 A6 v) m% U+ E dat$event <- event& E$ C" f ?# j: Y! T% i. L5 `
) T6 i$ u! n b0 q8 t9 J reclassification(data = dat,( p3 [+ a4 N# i4 m- ~: ~* k
cOutcome = 21, # 结果变量在哪一列
# E, Z% }* ]. f1 P predrisk1 = p.std,1 \' m |; X1 e$ d( s$ W" u# a/ a4 i
predrisk2 = p.new,& D' ~( X* N, Y, T. n' N1 q' L! W
cutoff = c(0,0.3,0.7,1)
1 y# w1 [+ q" |9 v$ D5 n) ~) v )
. O3 f0 I" F7 b# c' `4 m 1
# W, b0 T7 R1 N# T- R. f ## _________________________________________
) `* r! B2 ~9 R2 B ##
: m" S% B4 a1 M2 b0 d1 Z% G ## Reclassification table
( n) s% K3 i& ^: g ## _________________________________________# a& I( L% O v7 A9 h
##
. }0 O7 l% D) U ## Outcome: absent
6 H9 }9 y- m8 F/ `7 V0 k2 x ## # q6 T! d; A( N+ }% X3 {
## Updated Model
: A! q# ^" l( X- E; R ## Initial Model [0,0.3) [0.3,0.7) [0.7,1] % reclassified4 p" x6 ^2 {% ~' F# Y: M1 B
## [0,0.3) 121 4 0 3% f. G4 {8 P/ U' A/ k3 _
## [0.3,0.7) 1 13 1 13) m& o" T2 x4 ~+ b
## [0.7,1] 0 1 3 25. H! t5 L4 z" K3 d2 V
## - r# l( n& u: C" z
## - c0 j- G) P* U3 w1 h# Y. p
## Outcome: present - G; n1 d" z# T9 `6 l6 N/ }
## 0 j' O* {: y3 b5 q# N
## Updated Model! U6 C8 p+ L. i8 O: S" M9 M
## Initial Model [0,0.3) [0.3,0.7) [0.7,1] % reclassified" J6 A( Y) T0 `9 A) W" g4 d
## [0,0.3) 14 0 0 0. _: O: m) x$ g u9 u
## [0.3,0.7) 0 18 3 14; E; A5 Z H. e
## [0.7,1] 0 1 52 2
. f, @4 Y d# N7 K7 d3 v ##
. o8 i/ {4 W3 z8 ^8 m ## 2 S& I3 U" g0 g7 S; G1 i0 `, x7 H( ^
## Combined Data ) c& J( K3 x. u/ }2 _
##
" U: X H7 C7 l2 O- Y* \/ { ## Updated Model
* d" `: N" d: Q. X) M& K ## Initial Model [0,0.3) [0.3,0.7) [0.7,1] % reclassified: M0 Z7 ]. Y8 M, i. I
## [0,0.3) 135 4 0 3
; x% K' w7 R. t/ n0 s, w: i/ x ## [0.3,0.7) 1 31 4 143 l. a# [7 C# E1 a! s* V2 b
## [0.7,1] 0 2 55 4
! C1 w+ H. i$ X+ A! P ## _________________________________________0 u! I c: Z, x ^9 U5 C
##
3 E. R, j; P- p1 ]% X* |! k ## NRI(Categorical) [95% CI]: 0.0019 [ -0.0551 - 0.0589 ] ; p-value: 0.94806
0 x4 f; Y. Q$ Z, t1 u& u7 l9 h% y ## NRI(Continuous) [95% CI]: 0.0391 [ -0.2238 - 0.3021 ] ; p-value: 0.77048
1 k) j: e) }/ E9 @( ]; N, W- x ## IDI [95% CI]: 0.0044 [ -0.0037 - 0.0126 ] ; p-value: 0.283961 ?3 Z6 H( v9 Z! e3 B) ], ]
4 I$ T+ w' R6 E& Z
1. B1 t! D; K$ Z* @0 R) f
结果得到的是相加净重分类指数,还给出了IDI和P值。两个包算是各有优劣吧,大家可以自由选择。/ S9 _8 X. L( {$ m
. ]( w+ u& W) o: H' n 生存分析的NRI
% |' ]/ @# ~# ^0 p! V$ q& ` 还是使用survival包中的pbc数据集用于演示,这次要构建cox回归模型,因此我们要使用time这一列了。
) V( J5 N8 I' O/ j7 l
( P, a( x: `6 y/ Q) U nricens包& w8 |0 m1 U4 i8 A" g
library(nricens)3 ^% T. q2 K# W: O8 z4 K
library(survival) ]2 g, x5 q, b: w2 T! P
R9 f% h& ?6 e3 B P5 e dat <- pbc[1:312,]8 m% |* v0 r' \
dat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡. H; N0 U, t5 q% Q% }
1
' n. { G4 A% l: j4 i" I( x! }; a 然后准备所需参数:" P& i1 s' P6 Y& h9 W7 x; ?6 u
! y4 r2 G( I5 J& A" P/ F
# 两个只由预测变量组成的矩阵
6 ^) K8 T: o' n( ?& Z! @8 o7 o2 D z.std = as.matrix(subset(dat, select = c(age, bili, albumin)))9 ` j; |1 P( L0 J# d
z.new = as.matrix(subset(dat, select = c(age, bili, albumin, protime)))
2 P5 A8 b3 Y( d( G1 ? 7 @3 E4 v. E* ~4 `& ~: x" H
# 建立2个cox模型
" |% G3 r9 x, E; ^. Z& \9 u mstd <- coxph(Surv(time,status) ~ age + bili + albumin, data = dat, x=TRUE)
% o- S1 `# W- H j3 B+ M- u' ] mnew <- coxph(Surv(time,status) ~ age + bili + albumin + protime, data = dat, x=TRUE)6 Z) a( i. q5 V: c# u7 h
: Z) N( c1 y9 }/ `. V" ] # 计算在2000天的模型预测概率,这一步不要也行,看你使用哪些参数' P4 `- B& k1 Z1 \
p.std <- get.risk.coxph(mstd, t0=2000)
4 I5 Q X) p1 y p.new <- get.risk.coxph(mnew, t0=2000)
. k& R+ a& ^' }. B 1/ W, O n5 a) o
计算NRI:
8 C( }$ h9 Q8 R0 k3 }7 t
! F, ]) o9 f8 |, Q, r. b% L/ m nricens(mdl.std= mstd, mdl.new = mnew, 6 D1 W8 o$ p) `1 L, J- E9 j
t0 = 2000,
, i5 v" B k. w8 v+ W2 [2 I& F cut = c(0.3, 0.7),0 F4 d2 j; G9 _+ ^5 _
niter = 1000,
2 T" m# j9 \" F5 U2 h updown = 'category')
; h0 r, q' x; K4 q8 {, N1 X6 E 2 ^' j9 X% I% X9 o
UP and DOWN calculation:% r% }: F& Q$ {; n t
#of total, case, and control subjects at t0: 312 88 144
+ U! X2 d% \4 V7 j * d6 ~- P# T/ S+ O: H
Reclassification Table for all subjects:) N1 D6 I6 E1 q( x. C* \
New m! H8 P2 `2 _5 u6 A
Standard < 0.3 < 0.7 >= 0.7% ?' q$ k( T! F9 P, X
< 0.3 202 7 0
( P* M& h5 k7 ~0 w < 0.7 13 53 6
) C. w9 Z; ], H4 O >= 0.7 0 0 31
; C8 z% E# A" }& `# X
/ d; p: l2 w2 i- K( j. h: k Reclassification Table for case:. h! c: T. ]/ [! V1 B" f
New
9 y8 x! P" [1 m Standard < 0.3 < 0.7 >= 0.76 G/ }: @' u' Q( V
< 0.3 19 3 09 s' b7 F# R- w+ o1 g7 t) }4 _
< 0.7 3 32 4
8 f, m* T1 g$ e& G9 ?( T >= 0.7 0 0 27 T7 y1 C# C( j1 Y5 l
# L/ K# U4 K4 {$ ~9 P Reclassification Table for control:. r& J7 U' T* k f; N% V- Y
New
, I$ \4 v( a% F& t0 Q& y/ E Standard < 0.3 < 0.7 >= 0.7
/ ^- i1 q, _& z) |% X- k* g% e2 E < 0.3 126 3 0
; a4 Q8 U" E C+ I1 c, c < 0.7 5 7 21 f) |# _& V0 W& p
>= 0.7 0 0 16 C# y2 |) ~3 R/ H
7 m. n+ p( u8 G( o; x NRI estimation by KM estimator:
' Z/ @* v) n6 \ . Z4 ~9 }" b) Y
Point estimates:$ f1 [5 c# }$ ]
Estimate/ { n% f j- V7 ]. V
NRI 0.05377635$ d' Q. i5 X- a" W( v9 {* Y
NRI+ 0.03748660
; _% I" l! ]7 g! e- Q) b) ? NRI- 0.01628974
1 o1 d6 b/ ^. N/ Y0 ~! _ Pr(Up|Case) 0.07708938$ z0 Q! q- K& R/ ~0 j. c
Pr(Down|Case) 0.039602786 ?. G S! O, r% u( W- `. e
Pr(Down|Ctrl) 0.04256352
6 Y0 C1 A# ^$ `1 X1 \: z- P Pr(Up|Ctrl) 0.026273782 d W/ A: |# I: `( o' k
( y0 q, g9 S& Q0 U
Now in bootstrap..
) a& [: e) \3 T8 L' [ Y3 r
) Q' _( L7 L* k0 F5 s* }: Y Point & Interval estimates:0 e2 k/ J" M4 h7 H9 X9 u4 s
Estimate Lower Upper3 [8 @& i6 B1 ` o7 ^" Q: N( k7 L
NRI 0.05377635 -0.082230381 0.16058172
$ `. q) k h$ y4 f7 c/ ? NRI+ 0.03748660 -0.084245197 0.13231776
# Z. r: G/ N. E NRI- 0.01628974 -0.030861213 0.06753616
0 L: |0 _# F/ r9 D* h Pr(Up|Case) 0.07708938 0.000000000 0.19102291
1 [8 N0 h! |+ E9 m Pr(Down|Case) 0.03960278 0.000000000 0.15236016; B- [1 c, t3 r4 e
Pr(Down|Ctrl) 0.04256352 0.004671535 0.09863170
# i" j' N2 u$ d4 f* `. B2 L/ ?: S Pr(Up|Ctrl) 0.02627378 0.006400463 0.05998424( B+ x- M8 M/ u* R& x+ V
7 K5 E9 E+ W: p4 |4 E2 J
1 t. J3 d2 g: T9 z
$ h b2 J5 X( R7 Y7 {9 h8 |) D Snipaste_2022-05-20_21-49-38# e- D) O0 c. c. S7 ^5 ]
结果的解读和logistic的一模一样。
7 K( i$ R; U9 g: R / B/ U8 o& p# K+ h
survNRI包1 o1 ]- z& t8 d) X' T
# 安装R包
, \5 k; k* L* u8 ]. S& C devtools::install_github("mdbrown/survNRI")) k, g) a) t: m
16 q o N3 ]* S9 Z
加载R包并使用,还是用上面的pbc数据集。
) h- D6 R' J4 A9 D' a& g " Q& z& W4 }' S& s; A! ?7 `: x9 B& z
library(survNRI)
* j v. M7 Q* @: v 1
2 d* e6 q. b1 J* Y2 p# @+ P' A ## Loading required package: MASS
$ ^7 @9 A8 M( R 1
* f' ]1 [% R- B library(survival)2 L! W2 ~3 ~# J# [
- `' ~2 m2 g9 ]6 O" q
# 使用部分数据" O0 |3 h* G7 y3 R4 H
dat <- pbc[1:312,]& {3 ]9 ], F4 H0 } p" o+ _
dat$status <- ifelse(dat$status==2, 1, 0) # 0表示活着,1表示死亡4 O, V3 a; W" `4 b7 K4 ~, a
% }) W: J: a# A0 V res <- survNRI(time = "time", event = "status",
5 D* w# [0 N9 s3 @$ T model1 = c("age", "bili", "albumin"), # 模型1的自变量8 |9 s& w8 w* D7 s& V. M. g5 P2 r
model2 = c("age", "bili", "albumin", "protime"), # 模型2的自变量$ I4 Y9 A% E2 R+ ~# u
data = dat, * B, i! i7 ]2 s& K
predict.time = 2000, # 预测的时间点, w p/ X* i$ B. A! Z7 G
method = "all",
' ~8 U6 l- t0 V bootMethod = "normal",
8 [6 T- x/ g8 J3 m% W; I( g bootstraps = 500, ) }- J( A& k( w; I8 p
alpha = .05). h' j$ h: r8 X, v* A- b
, J" x3 h7 L; m' q 1
* r, O" |5 D6 n, ^- }" f 查看结果,$estimates给出了不同组的NRI以及总的NRI,包括了使用不同方法(KM/IPW/SmoothIPW/SEM/Combined)得到的结果;$CI给出了可信区间。
* G" t# b# {% o- Z E7 t: c
* N8 {' i- ]6 `, V$ P; O/ Y# D res
) K4 b! p9 y" p1 w7 z% x: t; B, c2 s 1: k9 F. o4 e3 @$ G, A: U
## $estimates: L& h/ H, C/ g% m1 a
## NRI.event NRI.nonevent NRI! Z8 h) f+ x; B$ k1 m0 u
## KM 0.20445422 0.3187408 0.5231951
4 e- J( H( v: H$ v" _: ` ## IPW 0.22424434 0.3273544 0.5515987
: d' G" Z( k3 z ## SmoothIPW 0.19645006 0.3144263 0.5108763, B) `3 |, e3 I3 `1 \
## SEM 0.07478611 0.2632127 0.33799887 k7 D. h& V. e2 `
## Combined 0.19633867 0.3143794 0.5107181! w& ], j4 P, X' C' u
##
" q) C$ M! S; ~, R) t ## $CI2 j* F) a: k1 d& Z. p2 h# `( V
## $CI$NRI.event1 ]- f+ O& ]6 S8 p8 X" e
## KM IPW SmoothIPW SEM Combined6 a' U! [6 A' s2 K
## lowerbound -0.03915924 -0.02185068 -0.04724202 -0.1162587 -0.04737235 M6 E% k* @6 m/ @5 y p
## upperbound 0.44806768 0.47033936 0.44014214 0.2658309 0.4400496
; u1 E. N& A, ]$ y ## 4 g# Q3 @1 c2 C2 P3 T5 {% W9 y
## $CI$NRI.nonevent* |1 r0 O) h" e" k
## KM IPW SmoothIPW SEM Combined
4 d- s2 z: {8 h- E2 Y4 k ## lowerbound 0.1317108 0.1396315 0.1286685 0.08638933 0.1286426- ], h n/ J8 Y
## upperbound 0.7102251 0.7393216 0.6966341 0.51482212 0.6964549
( Z4 W0 _/ I- V3 z ##
& A' h7 n. r' E& D7 f+ Y ## $CI$NRI
& A$ v B1 p0 c9 ] ## KM IPW SmoothIPW SEM Combined
: z2 s2 o7 |5 l* y) p6 D! H ## lowerbound -0.05112533 -0.04569046 -0.05439863 -0.04132364 -0.05443409
, u: w0 o: s" }! ^0 u/ @' Z6 E ## upperbound 0.89306122 0.92464359 0.87970125 0.64253510 0.879531535 `1 f/ p. b% i1 x. f$ l0 R+ _* M
## 7 E8 e' l' x6 K% _2 N
## : W3 D0 F: k, a6 g3 |' A4 b& e" M
## $bootMethod
+ A: J- b- E J, w) b ## [1] "normal". j" U+ P, A- K! N4 l# p
##
# _* g* n# c1 X* z% X4 [ ## $predict.time
( k0 h; d1 y: k8 \5 |2 B ## [1] 2000
' u. M5 f1 x) g7 J$ E+ E/ j ##
. Z. `. |, G3 x% K9 G ## $alpha7 e8 ]( }4 n$ x# U& E+ k
## [1] 0.05
. X" h! Q* u( N) m8 O% K$ K! e; m8 K ##
4 A+ @3 }# u0 r- \ ## attr(,"class")
5 U6 V/ y' c) X2 o3 b x( x ## [1] "survNRI"- |# r1 b! V( ]) H7 H! c i. j
$ \1 j& C# n$ y
1
( g$ U9 t% [, @4 e6 J7 } OK,这就是NRI的计算,除此之外,随机森林、决策树、lasso回归、SVM等,这些模型,都是可以计算的NRI的,后面会继续介绍。大家如果有问题欢迎在评论区留言。3 t: o: N; Y: U) s3 N! _6 W( e" l
- Q( y, _# |' p 本文首发于公众号:医学和生信笔记
6 S A5 q% N! G, r3 G% h2 O- i
* p2 ~4 D& ]: l h “ 医学和生信笔记,专注R语言在临床医学中的使用,R语言数据分析和可视化。主要分享R语言做医学统计学、meta分析、网络药理学、临床预测模型、机器学习、生物信息学等。
1 ]1 M2 N, I% s: V- } 本文由 mdnice 多平台发布0 M1 E; x4 L+ d$ @( `
————————————————
* c }' O \' B3 I5 q+ g6 l 版权声明:本文为CSDN博主「阿越就是我」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。8 J8 N1 ~" K3 M' H% A( w y3 r
原文链接:https://blog.csdn.net/Ayue0616/article/details/126768006
4 D/ p |: e0 n! B2 A0 [9 t! B9 @ & X7 @& @4 {$ Q, Y, k8 c+ y
4 e0 p/ w6 j3 q; t
zan