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