library(survival); library(tableone); library(prodlim); library(riskRegression); library(CalibrationCurves)
## riskRegression version 2023.09.08
## Loading required package: rms
## Loading required package: Hmisc
##
## Attaching package: 'Hmisc'
## The following objects are masked from 'package:base':
##
## format.pval, units
## Loading required package: ggplot2
wpps<- read.csv("C:\\Thach\\Research projects\\MSM and competing risk\\Data_Analysis\\wpp_s60.csv")
head(wpps)
## Fx1st_sen BMI_0 neuro_0 rheum_0 hypert_0 diabetes_0 respi_0 cancer_0 cvd_0
## 1 0 27.34 0 0 0 1 0 0 1
## 2 0 27.34 0 0 1 0 0 0 1
## 3 0 24.06 1 0 1 0 0 0 0
## 4 0 26.13 0 0 1 0 0 0 1
## 5 0 27.34 0 0 1 1 0 0 1
## 6 0 26.13 0 0 0 0 0 0 1
## prior_fx age StudyID sex falls_n death_sen fnbmd kmfu_fx kmfu_death
## 1 0 73.07 3 0 0 1 -0.3250 0.5475702 0.5475702
## 2 0 68.47 9 0 0 1 0.2250 5.0513347 5.0513347
## 3 0 62.10 10 1 0 1 1.3417 26.5735797 26.5735797
## 4 0 75.81 24 1 0 0 2.1417 2.8555784 2.8555784
## 5 0 63.53 26 0 0 0 0.2833 9.2621492 9.2621492
## 6 0 76.24 28 1 1 1 2.8833 20.5338809 20.5338809
## group
## 1 2
## 2 2
## 3 2
## 4 0
## 5 0
## 6 2
factorVars <- c("group","sex","falls_n","prior_fx","cvd_0","respi_0","diabetes_0","hypert_0","cancer_0","rheum_0","neuro_0")
Vars <- c("sex","age","fnbmd","falls_n","prior_fx","kmfu_fx","kmfu_death","BMI_0","cvd_0","respi_0","diabetes_0","hypert_0","cancer_0","rheum_0","neuro_0")
table.1d <- CreateTableOne(vars = Vars, strata = "group", data = wpps, factorVars = factorVars)
print(table.1d, nonnormal = c("kmfu_fx","kmfu_death"))
## Stratified by group
## 0 1
## n 1045 505
## sex = 1 (%) 646 (61.8) 389 (77.0)
## age (mean (SD)) 68.34 (5.74) 69.43 (6.31)
## fnbmd (mean (SD)) 1.16 (1.16) 1.80 (1.06)
## falls_n (%)
## 0 844 (80.8) 377 (74.7)
## 1 135 (12.9) 91 (18.0)
## 2 66 ( 6.3) 37 ( 7.3)
## prior_fx = 1 (%) 123 (11.8) 88 (17.4)
## kmfu_fx (median [IQR]) 9.65 [6.08, 13.65] 7.20 [3.24, 11.14]
## kmfu_death (median [IQR]) 9.65 [6.08, 13.65] 11.64 [7.93, 16.80]
## BMI_0 (mean (SD)) 27.19 (4.11) 26.56 (3.98)
## cvd_0 = 1 (%) 322 (30.8) 177 (35.0)
## respi_0 = 1 (%) 103 ( 9.9) 73 (14.5)
## diabetes_0 = 1 (%) 122 (11.7) 41 ( 8.1)
## hypert_0 = 1 (%) 539 (51.6) 257 (50.9)
## cancer_0 = 1 (%) 88 ( 8.4) 54 (10.7)
## rheum_0 = 1 (%) 23 ( 2.2) 30 ( 5.9)
## neuro_0 = 1 (%) 60 ( 5.7) 48 ( 9.5)
## Stratified by group
## 2 p test
## n 271
## sex = 1 (%) 120 (44.3) <0.001
## age (mean (SD)) 71.43 (6.93) <0.001
## fnbmd (mean (SD)) 1.31 (1.30) <0.001
## falls_n (%) 0.014
## 0 227 (83.8)
## 1 33 (12.2)
## 2 11 ( 4.1)
## prior_fx = 1 (%) 29 (10.7) 0.004
## kmfu_fx (median [IQR]) 6.50 [3.55, 11.37] <0.001 nonnorm
## kmfu_death (median [IQR]) 6.50 [3.55, 11.37] <0.001 nonnorm
## BMI_0 (mean (SD)) 26.82 (1.45) 0.008
## cvd_0 = 1 (%) 124 (45.8) <0.001
## respi_0 = 1 (%) 38 (14.0) 0.014
## diabetes_0 = 1 (%) 44 (16.2) 0.003
## hypert_0 = 1 (%) 138 (50.9) 0.960
## cancer_0 = 1 (%) 29 (10.7) 0.258
## rheum_0 = 1 (%) 15 ( 5.5) <0.001
## neuro_0 = 1 (%) 17 ( 6.3) 0.021
table(wpps$Fx1st_sen, wpps$sex)
##
## 0 1
## 0 550 766
## 1 116 389
mfit.con.f <- survfit(Surv(kmfu_fx, Fx1st_sen) ~ sex, data = wpps)
mfit.con.f
## Call: survfit(formula = Surv(kmfu_fx, Fx1st_sen) ~ sex, data = wpps)
##
## n events median 0.95LCL 0.95UCL
## sex=0 666 116 NA 21.4 NA
## sex=1 1155 389 17.2 16.3 18.3
table(wpps$death_sen, wpps$sex)
##
## 0 1
## 0 490 978
## 1 176 177
mfit.con.d <- survfit(Surv(kmfu_death, death_sen) ~ sex, data = wpps)
mfit.con.d
## Call: survfit(formula = Surv(kmfu_death, death_sen) ~ sex, data = wpps)
##
## n events median 0.95LCL 0.95UCL
## sex=0 666 176 21.4 19.4 26.6
## sex=1 1155 177 NA 26.6 NA
## Conventional model for fracture
cfit.con.f <- coxph(Surv(kmfu_fx, Fx1st_sen) ~ sex + age + fnbmd + falls_n + prior_fx,
data = wpps, id = StudyID)
summary(cfit.con.f)
## Call:
## coxph(formula = Surv(kmfu_fx, Fx1st_sen) ~ sex + age + fnbmd +
## falls_n + prior_fx, data = wpps, id = StudyID)
##
## n= 1821, number of events= 505
##
## coef exp(coef) se(coef) z Pr(>|z|)
## sex 0.394651 1.483867 0.111300 3.546 0.000391 ***
## age 0.042794 1.043723 0.008007 5.345 9.07e-08 ***
## fnbmd 0.404080 1.497923 0.047510 8.505 < 2e-16 ***
## falls_n 0.009253 1.009296 0.075632 0.122 0.902632
## prior_fx 0.397371 1.487908 0.123750 3.211 0.001322 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex 1.484 0.6739 1.1930 1.846
## age 1.044 0.9581 1.0275 1.060
## fnbmd 1.498 0.6676 1.3647 1.644
## falls_n 1.009 0.9908 0.8702 1.171
## prior_fx 1.488 0.6721 1.1675 1.896
##
## Concordance= 0.693 (se = 0.013 )
## Likelihood ratio test= 221.9 on 5 df, p=<2e-16
## Wald test = 228.3 on 5 df, p=<2e-16
## Score (logrank) test = 235.9 on 5 df, p=<2e-16
zph.cfit0f <- cox.zph(cfit.con.f)
zph.cfit0f
## chisq df p
## sex 0.024096 1 0.88
## age 1.118674 1 0.29
## fnbmd 0.179847 1 0.67
## falls_n 0.933495 1 0.33
## prior_fx 0.000869 1 0.98
## GLOBAL 3.268397 5 0.66
### Proportional hazards assumption
windows(width = 14, height = 12)
par(mfrow = c(3,2), oma = c(0,0,2,0))
plot(zph.cfit0f[1])
abline(h=coef(cfit.con.f)[1], lty=2, col=2)
plot(zph.cfit0f[2])
abline(h=coef(cfit.con.f)[2], lty=2, col=2)
plot(zph.cfit0f[3])
abline(h=coef(cfit.con.f)[3], lty=2, col=2)
plot(zph.cfit0f[4])
abline(h=coef(cfit.con.f)[4], lty=2, col=2)
plot(zph.cfit0f[5])
abline(h=coef(cfit.con.f)[5], lty=2, col=2)
mtext("Proportional hazards assumption: Conventional model", line=0, side=3, outer=TRUE, cex=1.8)
## Conventional model for death without a fracture
cfit.con.d <- coxph(Surv(kmfu_death, death_sen) ~ sex + age + fnbmd + falls_n + prior_fx,
data = wpps, id = StudyID)
summary(cfit.con.d)
## Call:
## coxph(formula = Surv(kmfu_death, death_sen) ~ sex + age + fnbmd +
## falls_n + prior_fx, data = wpps, id = StudyID)
##
## n= 1821, number of events= 353
##
## coef exp(coef) se(coef) z Pr(>|z|)
## sex -0.747923 0.473349 0.116521 -6.419 1.37e-10 ***
## age 0.131206 1.140203 0.009097 14.422 < 2e-16 ***
## fnbmd 0.127560 1.136054 0.054395 2.345 0.019 *
## falls_n -0.262873 0.768839 0.105832 -2.484 0.013 *
## prior_fx 0.097152 1.102028 0.168334 0.577 0.564
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex 0.4733 2.1126 0.3767 0.5948
## age 1.1402 0.8770 1.1201 1.1607
## fnbmd 1.1361 0.8802 1.0212 1.2639
## falls_n 0.7688 1.3007 0.6248 0.9461
## prior_fx 1.1020 0.9074 0.7923 1.5328
##
## Concordance= 0.749 (se = 0.014 )
## Likelihood ratio test= 273.6 on 5 df, p=<2e-16
## Wald test = 293.5 on 5 df, p=<2e-16
## Score (logrank) test = 319.4 on 5 df, p=<2e-16
zph.cfit0d <- cox.zph(cfit.con.d)
zph.cfit0d
## chisq df p
## sex 0.018 1 0.893
## age 1.445 1 0.229
## fnbmd 0.485 1 0.486
## falls_n 1.018 1 0.313
## prior_fx 3.454 1 0.063
## GLOBAL 6.833 5 0.233
etime <- with(wpps, ifelse(Fx1st_sen == 0, kmfu_death, kmfu_fx))
event <- with(wpps, ifelse(Fx1st_sen == 0, 2*death_sen, 1))
event <- factor(event, 0:2, labels=c("Event-free", "Fracture", "Death"))
table(event)
## event
## Event-free Fracture Death
## 1045 505 271
mfit.cs <- survfit(Surv(etime, event) ~ sex, data = wpps)
print(mfit.cs)
## Call: survfit(formula = Surv(etime, event) ~ sex, data = wpps)
##
## n nevent rmean*
## sex=0, (s0) 666 0 15.916935
## sex=1, (s0) 1155 0 14.892149
## sex=0, Fracture 666 116 5.696660
## sex=1, Fracture 1155 389 10.850160
## sex=0, Death 666 151 7.519875
## sex=1, Death 1155 120 3.391161
## *restricted mean time in state (max time = 29.13347 )
mfit.cs$transitions
## to
## from Fracture Death (censored)
## (s0) 505 271 1045
## Fracture 0 0 0
## Death 0 0 0
windows(width = 16, height = 12)
par(mfrow = c(1,2), oma = c(0,0,2,0))
plot(mfit.con.f[2], fun = "event", mark.time = FALSE, col = "black", lty = 1, lwd = 2, conf.int = FALSE,
xlab="Time (years)", ylab="Probability", ylim = c(0,1))
lines(mfit.con.d[2], fun = "event", mark.time = FALSE, col = "black", lty = 2, lwd = 2, conf.int = FALSE)
lines(mfit.cs[2,2], mark.time = FALSE, col = "red", lty = 1, lwd = 2, conf.int = FALSE)
lines(mfit.cs[2,3], mark.time = FALSE, col = "red", lty = 2, lwd = 2, conf.int = FALSE)
title(main = "Women", cex.main = 1.2)
plot(mfit.con.f[1], fun = "event", mark.time = FALSE, col = "black", lty = 1, lwd = 2, conf.int = FALSE,
xlab="Time (years)", ylab="Probability", ylim = c(0,1))
lines(mfit.con.d[1], fun = "event", mark.time = FALSE, col = "black", lty = 2, lwd = 2, conf.int = FALSE)
lines(mfit.cs[1,2], mark.time = FALSE, col = "red", lty = 1, lwd = 2, conf.int = FALSE)
lines(mfit.cs[1,3], mark.time = FALSE, col = "red", lty = 2, lwd = 2, conf.int = FALSE)
title(main = "Men", cex.main = 1.2)
legend("topleft", c("Fracture (Conventional)","Death (Conventional)", "Fracture (Competing risk)", "death_sen (Competing risk)"),
col = c("black","black","red","red"), lty = c(1,2,1,2), lwd = 2, bty = 'n', cex = 0.8)
mtext("Risk of fracture and death by different methods", line = 0, side = 3,
outer = TRUE, cex = 1.6)
## For descriptive graphs:
csfit <- coxph(Surv(etime, event) ~ sex + age + fnbmd + falls_n + prior_fx,
data = wpps, id = StudyID)
summary(csfit)
## Call:
## coxph(formula = Surv(etime, event) ~ sex + age + fnbmd + falls_n +
## prior_fx, data = wpps, id = StudyID)
##
## n= 1821, number of events= 776
##
## coef exp(coef) se(coef) robust se z Pr(>|z|)
## sex_1:2 0.394651 1.483867 0.111300 0.111066 3.553 0.00038 ***
## age_1:2 0.042794 1.043723 0.008007 0.008289 5.163 2.43e-07 ***
## fnbmd_1:2 0.404080 1.497923 0.047510 0.047542 8.499 < 2e-16 ***
## falls_n_1:2 0.009253 1.009296 0.075632 0.079901 0.116 0.90781
## prior_fx_1:2 0.397371 1.487908 0.123750 0.129847 3.060 0.00221 **
## sex_1:3 -0.733062 0.480436 0.131771 0.139419 -5.258 1.46e-07 ***
## age_1:3 0.127076 1.135503 0.010267 0.010603 11.985 < 2e-16 ***
## fnbmd_1:3 0.031901 1.032415 0.061144 0.070864 0.450 0.65259
## falls_n_1:3 -0.352542 0.702899 0.129767 0.128472 -2.744 0.00607 **
## prior_fx_1:3 0.010446 1.010501 0.205829 0.212640 0.049 0.96082
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex_1:2 1.4839 0.6739 1.1936 1.8447
## age_1:2 1.0437 0.9581 1.0269 1.0608
## fnbmd_1:2 1.4979 0.6676 1.3647 1.6442
## falls_n_1:2 1.0093 0.9908 0.8630 1.1804
## prior_fx_1:2 1.4879 0.6721 1.1536 1.9191
## sex_1:3 0.4804 2.0814 0.3656 0.6314
## age_1:3 1.1355 0.8807 1.1121 1.1593
## fnbmd_1:3 1.0324 0.9686 0.8985 1.1862
## falls_n_1:3 0.7029 1.4227 0.5464 0.9042
## prior_fx_1:3 1.0105 0.9896 0.6661 1.5330
##
## Concordance= 0.711 (se = 0.01 )
## Likelihood ratio test= 417 on 10 df, p=<2e-16
## Wald test = 463.9 on 10 df, p=<2e-16
## Score (logrank) test = 461.1 on 10 df, p=<2e-16, Robust = 291.8 p=<2e-16
##
## (Note: the likelihood ratio and score tests assume independence of
## observations within a cluster, the Wald and robust score tests do not).
zph.csfit <- cox.zph(csfit)
zph.csfit
## chisq df p
## sex_1:2 0.029118 1 0.865
## age_1:2 1.114354 1 0.291
## fnbmd_1:2 0.182523 1 0.669
## falls_n_1:2 0.887880 1 0.346
## prior_fx_1:2 0.000837 1 0.977
## sex_1:3 0.125561 1 0.723
## age_1:3 1.210546 1 0.271
## fnbmd_1:3 0.120813 1 0.728
## falls_n_1:3 0.861422 1 0.353
## prior_fx_1:3 3.036326 1 0.081
## GLOBAL 8.724266 10 0.558
windows(width = 14, height = 12)
par(mfrow=c(2,5), oma=c(0,0,2,0))
plot(zph.csfit[1])
abline(h=coef(csfit)[1], lty=2, col=1)
title(main = "Fracture model", cex.main= 1.5)
plot(zph.csfit[2])
abline(h=coef(csfit)[2], lty=2, col=1)
plot(zph.csfit[3])
abline(h=coef(csfit)[3], lty=2, col=1)
plot(zph.csfit[4])
abline(h=coef(csfit)[4], lty=2, col=1)
plot(zph.csfit[5])
abline(h=coef(csfit)[5], lty=2, col=1)
plot(zph.csfit[6])
abline(h=coef(csfit)[6], lty=2, col=2)
title(main = "Mortality model", cex.main= 1.5)
plot(zph.csfit[7])
abline(h=coef(csfit)[7], lty=2, col=2)
plot(zph.csfit[8])
abline(h=coef(csfit)[8], lty=2, col=2)
plot(zph.csfit[9])
abline(h=coef(csfit)[9], lty=2, col=2)
plot(zph.csfit[10])
abline(h=coef(csfit)[10], lty=2, col=2)
mtext("Sensitivity analysis- PH assumption: Cause-specific model", line=0, side=3, outer=TRUE, cex=1.8)
# For prediction of absolute risk: 'CSC' from riskRegression using the combined coefficients
CSC.fit <- CSC(Hist(etime, event)~ sex + age + fnbmd + falls_n + prior_fx,
data = wpps, method = "breslow")
print(CSC.fit)
## CSC(formula = Hist(etime, event) ~ sex + age + fnbmd + falls_n +
## prior_fx, data = wpps, method = "breslow")
##
## Uncensored response of a competing.risks model
##
## No.Observations: 1821
##
## Pattern:
##
## Cause event
## Event-free 1045
## Fracture 505
## Death 271
## unknown 0
##
##
## ----------> Cause: Event-free
##
## Call:
## coxph(formula = survival::Surv(time, status) ~ sex + age + fnbmd +
## falls_n + prior_fx, x = TRUE, y = TRUE, method = "breslow")
##
## n= 1821, number of events= 1045
##
## coef exp(coef) se(coef) z Pr(>|z|)
## sex 0.055579 1.057152 0.068079 0.816 0.41428
## age 0.069721 1.072209 0.006156 11.326 < 2e-16 ***
## fnbmd -0.080099 0.923025 0.031174 -2.569 0.01019 *
## falls_n -0.123397 0.883912 0.059071 -2.089 0.03671 *
## prior_fx 0.339550 1.404316 0.099942 3.397 0.00068 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex 1.0572 0.9459 0.9251 1.2081
## age 1.0722 0.9327 1.0593 1.0852
## fnbmd 0.9230 1.0834 0.8683 0.9812
## falls_n 0.8839 1.1313 0.7873 0.9924
## prior_fx 1.4043 0.7121 1.1545 1.7082
##
## Concordance= 0.614 (se = 0.01 )
## Likelihood ratio test= 138.7 on 5 df, p=<2e-16
## Wald test = 152.3 on 5 df, p=<2e-16
## Score (logrank) test = 154.3 on 5 df, p=<2e-16
##
##
##
## ----------> Cause: Fracture
##
## Call:
## coxph(formula = survival::Surv(time, status) ~ sex + age + fnbmd +
## falls_n + prior_fx, x = TRUE, y = TRUE, method = "breslow")
##
## n= 1821, number of events= 505
##
## coef exp(coef) se(coef) z Pr(>|z|)
## sex 0.394636 1.483844 0.111300 3.546 0.000392 ***
## age 0.042792 1.043720 0.008007 5.344 9.07e-08 ***
## fnbmd 0.404020 1.497834 0.047507 8.504 < 2e-16 ***
## falls_n 0.009284 1.009327 0.075632 0.123 0.902308
## prior_fx 0.397346 1.487871 0.123748 3.211 0.001323 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex 1.484 0.6739 1.1930 1.846
## age 1.044 0.9581 1.0275 1.060
## fnbmd 1.498 0.6676 1.3647 1.644
## falls_n 1.009 0.9908 0.8703 1.171
## prior_fx 1.488 0.6721 1.1674 1.896
##
## Concordance= 0.693 (se = 0.013 )
## Likelihood ratio test= 221.9 on 5 df, p=<2e-16
## Wald test = 228.3 on 5 df, p=<2e-16
## Score (logrank) test = 235.8 on 5 df, p=<2e-16
##
##
##
## ----------> Cause: Death
##
## Call:
## coxph(formula = survival::Surv(time, status) ~ sex + age + fnbmd +
## falls_n + prior_fx, x = TRUE, y = TRUE, method = "breslow")
##
## n= 1821, number of events= 271
##
## coef exp(coef) se(coef) z Pr(>|z|)
## sex -0.73304 0.48044 0.13177 -5.563 2.65e-08 ***
## age 0.12707 1.13550 0.01027 12.377 < 2e-16 ***
## fnbmd 0.03190 1.03241 0.06114 0.522 0.6019
## falls_n -0.35250 0.70293 0.12977 -2.716 0.0066 **
## prior_fx 0.01044 1.01049 0.20583 0.051 0.9596
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex 0.4804 2.0814 0.3711 0.6220
## age 1.1355 0.8807 1.1129 1.1586
## fnbmd 1.0324 0.9686 0.9158 1.1639
## falls_n 0.7029 1.4226 0.5451 0.9065
## prior_fx 1.0105 0.9896 0.6750 1.5126
##
## Concordance= 0.745 (se = 0.016 )
## Likelihood ratio test= 195.1 on 5 df, p=<2e-16
## Wald test = 210 on 5 df, p=<2e-16
## Score (logrank) test = 225.2 on 5 df, p=<2e-16
fgdata.fx <- finegray(Surv(etime, event) ~ ., data = wpps, etype = "Fracture")
fgdata.death <- finegray(Surv(etime, event) ~ ., data = wpps, etype = "Death")
mfit.fg <- survfit(Surv(fgstart, fgstop, fgstatus) ~ sex, data = fgdata.fx)
fgfit.f <- coxph(Surv(fgstart, fgstop, fgstatus) ~ sex + age + fnbmd + falls_n + prior_fx,
data = fgdata.fx, weight= fgwt)
summary(fgfit.f)
## Call:
## coxph(formula = Surv(fgstart, fgstop, fgstatus) ~ sex + age +
## fnbmd + falls_n + prior_fx, data = fgdata.fx, weights = fgwt)
##
## n= 49711, number of events= 505
##
## coef exp(coef) se(coef) robust se z Pr(>|z|)
## sex 0.532712 1.703547 0.110046 0.104024 5.121 3.04e-07 ***
## age 0.011767 1.011836 0.007528 0.006885 1.709 0.08744 .
## fnbmd 0.365037 1.440567 0.044831 0.040265 9.066 < 2e-16 ***
## falls_n 0.103195 1.108708 0.074308 0.071336 1.447 0.14801
## prior_fx 0.338834 1.403311 0.122979 0.117573 2.882 0.00395 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex 1.704 0.5870 1.3893 2.089
## age 1.012 0.9883 0.9983 1.026
## fnbmd 1.441 0.6942 1.3313 1.559
## falls_n 1.109 0.9020 0.9640 1.275
## prior_fx 1.403 0.7126 1.1145 1.767
##
## Concordance= 0.683 (se = 0.012 )
## Likelihood ratio test= 176.2 on 5 df, p=<2e-16
## Wald test = 224.6 on 5 df, p=<2e-16
## Score (logrank) test = 177.7 on 5 df, p=<2e-16, Robust = 165.7 p=<2e-16
##
## (Note: the likelihood ratio and score tests assume independence of
## observations within a cluster, the Wald and robust score tests do not).
zph.fgfit.f <- cox.zph(fgfit.f)
zph.fgfit.f
## chisq df p
## sex 1.081 1 0.29855
## age 11.796 1 0.00059
## fnbmd 4.834 1 0.02790
## falls_n 0.453 1 0.50082
## prior_fx 1.563 1 0.21121
## GLOBAL 14.964 5 0.01052
windows(width = 14, height = 12)
par(mfrow=c(3,2), oma=c(0,0,2,0))
plot(zph.fgfit.f[1])
abline(h=coef(fgfit.f)[1], lty=2, col=2)
plot(zph.fgfit.f[2])
abline(h=coef(fgfit.f)[2], lty=2, col=2)
plot(zph.fgfit.f[3])
abline(h=coef(fgfit.f)[3], lty=2, col=2)
plot(zph.fgfit.f[4])
abline(h=coef(fgfit.f)[4], lty=2, col=2)
plot(zph.fgfit.f[5])
abline(h=coef(fgfit.f)[5], lty=2, col=2)
mtext("Proportional hazards assumption: Fine-Gray model", line=0, side=3, outer=TRUE, cex=1.8)
msm.data <- tmerge(wpps, wpps, id = StudyID, death_sen = event(kmfu_death, death_sen),
Fx1st_sen = event(kmfu_fx, Fx1st_sen))
msm.data <- tmerge(msm.data, msm.data, StudyID, enum = cumtdc(tstart))
head(msm.data)
## Fx1st_sen BMI_0 neuro_0 rheum_0 hypert_0 diabetes_0 respi_0 cancer_0 cvd_0
## 1 0 27.34 0 0 0 1 0 0 1
## 2 0 27.34 0 0 1 0 0 0 1
## 3 0 24.06 1 0 1 0 0 0 0
## 4 0 26.13 0 0 1 0 0 0 1
## 5 0 27.34 0 0 1 1 0 0 1
## 6 0 26.13 0 0 0 0 0 0 1
## prior_fx age StudyID sex falls_n death_sen fnbmd kmfu_fx kmfu_death
## 1 0 73.07 3 0 0 1 -0.3250 0.5475702 0.5475702
## 2 0 68.47 9 0 0 1 0.2250 5.0513347 5.0513347
## 3 0 62.10 10 1 0 1 1.3417 26.5735797 26.5735797
## 4 0 75.81 24 1 0 0 2.1417 2.8555784 2.8555784
## 5 0 63.53 26 0 0 0 0.2833 9.2621492 9.2621492
## 6 0 76.24 28 1 1 1 2.8833 20.5338809 20.5338809
## group tstart tstop enum
## 1 2 0 0.5475702 1
## 2 2 0 5.0513347 1
## 3 2 0 26.5735797 1
## 4 0 0 2.8555784 1
## 5 0 0 9.2621492 1
## 6 2 0 20.5338809 1
with(msm.data, table(death_sen, Fx1st_sen))
## Fx1st_sen
## death_sen 0 1
## 0 1468 436
## 1 353 0
temp <- with(msm.data, ifelse(death_sen==1, 2, Fx1st_sen))
msm.data$event <- factor(temp, 0:2, labels=c("Event-free", "Fracture", "Death"))
mfit.msm1 <- survfit(Surv(tstart, tstop, event) ~ sex, data = msm.data, id = StudyID)
mfit.msm1
## Call: survfit(formula = Surv(tstart, tstop, event) ~ sex, data = msm.data,
## id = StudyID)
##
## n nevent rmean*
## sex=0, (s0) 760 0 16.584865
## sex=1, (s0) 1497 0 15.877738
## sex=0, Fracture 760 94 2.634750
## sex=1, Fracture 1497 342 7.172635
## sex=0, Death 760 176 9.913855
## sex=1, Death 1497 177 6.083096
## *restricted mean time in state (max time = 29.13347 )
mfit.msm1$transitions
## to
## from Fracture Death (censored)
## (s0) 436 271 1114
## Fracture 0 82 354
## Death 0 0 0
temp2 <- with(msm.data, ifelse(enum==2 & event=='Death', 4, as.numeric(event)))
table(temp2)
## temp2
## 1 2 3 4
## 1468 436 271 82
temp3 <- factor(temp2, labels=c("Event-free", "Fracture", "Death w/o fracture", "Death post fracture"))
table(temp3)
## temp3
## Event-free Fracture Death w/o fracture Death post fracture
## 1468 436 271 82
mfit.msm2 <- survfit(Surv(tstart, tstop, temp3) ~ sex, data = msm.data, id = StudyID)
print(mfit.msm2)
## Call: survfit(formula = Surv(tstart, tstop, temp3) ~ sex, data = msm.data,
## id = StudyID)
##
## n nevent rmean*
## sex=0, (s0) 760 0 16.584865
## sex=1, (s0) 1497 0 15.877738
## sex=0, Fracture 760 94 2.634750
## sex=1, Fracture 1497 342 7.172635
## sex=0, Death w/o fracture 760 151 7.824149
## sex=1, Death w/o fracture 1497 120 3.587283
## sex=0, Death post fracture 760 25 2.089707
## sex=1, Death post fracture 1497 57 2.495813
## *restricted mean time in state (max time = 29.13347 )
msmfit <- coxph(Surv(tstart, tstop, event) ~ sex + age +fnbmd + falls_n + prior_fx,
data = msm.data, id = StudyID)
summary(msmfit)
## Call:
## coxph(formula = Surv(tstart, tstop, event) ~ sex + age + fnbmd +
## falls_n + prior_fx, data = msm.data, id = StudyID)
##
## n= 2257, number of events= 789
##
## coef exp(coef) se(coef) robust se z Pr(>|z|)
## sex_1:2 0.484042 1.622620 0.121971 0.123186 3.929 8.52e-05 ***
## age_1:2 0.030720 1.031197 0.008691 0.009045 3.397 0.000682 ***
## fnbmd_1:2 0.402157 1.495046 0.050721 0.051157 7.861 3.80e-15 ***
## falls_n_1:2 0.025733 1.026067 0.081235 0.086838 0.296 0.766977
## prior_fx_1:2 0.370094 1.447871 0.133482 0.140989 2.625 0.008665 **
## sex_1:3 -0.731544 0.481165 0.131667 0.139269 -5.253 1.50e-07 ***
## age_1:3 0.127881 1.136418 0.010263 0.010593 12.073 < 2e-16 ***
## fnbmd_1:3 0.034614 1.035220 0.061108 0.070760 0.489 0.624722
## falls_n_1:3 -0.348446 0.705784 0.129952 0.128053 -2.721 0.006506 **
## prior_fx_1:3 0.014681 1.014789 0.205793 0.212689 0.069 0.944970
## sex_2:3 -1.170363 0.310254 0.275851 0.267189 -4.380 1.19e-05 ***
## age_2:3 0.157412 1.170478 0.021315 0.020866 7.544 4.56e-14 ***
## fnbmd_2:3 0.343225 1.409485 0.124269 0.126827 2.706 0.006805 **
## falls_n_2:3 -0.051889 0.949435 0.183594 0.188336 -0.276 0.782924
## prior_fx_2:3 0.145217 1.156291 0.300550 0.297771 0.488 0.625775
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex_1:2 1.6226 0.6163 1.2746 2.0657
## age_1:2 1.0312 0.9697 1.0131 1.0496
## fnbmd_1:2 1.4950 0.6689 1.3524 1.6527
## falls_n_1:2 1.0261 0.9746 0.8655 1.2164
## prior_fx_1:2 1.4479 0.6907 1.0983 1.9087
## sex_1:3 0.4812 2.0783 0.3662 0.6322
## age_1:3 1.1364 0.8800 1.1131 1.1603
## fnbmd_1:3 1.0352 0.9660 0.9012 1.1892
## falls_n_1:3 0.7058 1.4169 0.5491 0.9071
## prior_fx_1:3 1.0148 0.9854 0.6689 1.5396
## sex_2:3 0.3103 3.2232 0.1838 0.5238
## age_2:3 1.1705 0.8544 1.1236 1.2193
## fnbmd_2:3 1.4095 0.7095 1.0993 1.8072
## falls_n_2:3 0.9494 1.0533 0.6564 1.3733
## prior_fx_2:3 1.1563 0.8648 0.6451 2.0727
##
## Concordance= 0.711 (se = 0.01 )
## Likelihood ratio test= 459.4 on 15 df, p=<2e-16
## Wald test = 521.4 on 15 df, p=<2e-16
## Score (logrank) test = 501.8 on 15 df, p=<2e-16, Robust = 275.5 p=<2e-16
##
## (Note: the likelihood ratio and score tests assume independence of
## observations within a cluster, the Wald and robust score tests do not).
zph.msmfit <- cox.zph(msmfit)
zph.msmfit
## chisq df p
## sex_1:2 0.00323 1 0.955
## age_1:2 0.04012 1 0.841
## fnbmd_1:2 0.81804 1 0.366
## falls_n_1:2 1.65837 1 0.198
## prior_fx_1:2 0.09868 1 0.753
## sex_1:3 0.08792 1 0.767
## age_1:3 1.43172 1 0.231
## fnbmd_1:3 0.07019 1 0.791
## falls_n_1:3 1.12477 1 0.289
## prior_fx_1:3 3.14762 1 0.076
## sex_2:3 0.10321 1 0.748
## age_2:3 0.12452 1 0.724
## fnbmd_2:3 3.10354 1 0.078
## falls_n_2:3 0.05893 1 0.808
## prior_fx_2:3 1.43041 1 0.232
## GLOBAL 15.09513 15 0.445
windows(width = 14, height = 12)
par(mfrow=c(3,2), oma=c(0,0,2,0))
plot(zph.msmfit[1])
abline(h=coef(msmfit)[1], lty=2, col=2)
plot(zph.msmfit[2])
abline(h=coef(msmfit)[2], lty=2, col=2)
plot(zph.msmfit[3])
abline(h=coef(msmfit)[3], lty=2, col=2)
plot(zph.msmfit[4])
abline(h=coef(msmfit)[4], lty=2, col=2)
plot(zph.msmfit[5])
abline(h=coef(msmfit)[5], lty=2, col=2)
mtext("Proportional hazards assumption: Multistate model", line=0, side=3, outer=TRUE, cex=1.8)
windows(width = 16, height = 12)
par(mfrow=c(1,2), oma=c(0,0,2,0))
plot(mfit.con.f[2], col = "black", lty = 1, fun = "event", mark.time = FALSE, lwd = 2, conf.int = FALSE,
xlab="Time to event (years)", ylab="Probability of event", ylim = c(0,1))
lines(mfit.con.d[2], fun = "event", mark.time = FALSE, col = "black", lty = 2, lwd = 2, conf.int = FALSE)
lines(mfit.cs[2,2], fun = "event", mark.time = FALSE, col = "red", lty = 1, lwd = 2, conf.int = FALSE)
lines(mfit.fg[2], fun = "event", mark.time = FALSE, col = "blue", lty = 1, lwd = 2, conf.int = FALSE)
lines(mfit.msm2[2,2], fun = "event", mark.time = FALSE, col = "green", lty = 1, lwd = 2, conf.int = FALSE)
lines(mfit.msm2[2,4], fun = "event", mark.time = FALSE, col = "green", lty = 3, lwd = 2, conf.int = FALSE)
title(main= "Women")
plot(mfit.con.f[1], col = "black", lty = 1, fun = "event", mark.time = FALSE, lwd = 2, conf.int = FALSE,
xlab="Time to event (years)", ylab="Probability in State", ylim = c(0,1))
lines(mfit.con.d[1], fun = "event", mark.time = FALSE, col = "black", lty = 2, lwd = 2, conf.int = FALSE)
lines(mfit.cs[1,2], fun = "event", mark.time = FALSE, col = "red", lty = 1, lwd = 2, conf.int = FALSE)
lines(mfit.fg[1], fun = "event", mark.time = FALSE, col = "blue", lty = 1, lwd = 2, conf.int = FALSE)
lines(mfit.msm2[1,2], fun = "event", mark.time = FALSE, col = "green", lty = 1, lwd = 2, conf.int = FALSE)
lines(mfit.msm2[1,4], fun = "event", mark.time = FALSE, col = "green", lty = 3, lwd = 2, conf.int = FALSE)
legend("topleft", c("Fracture (Conventional)", "Death (Conventional)", "Fracture (Cause-specific)",
"Fracture (Fine-Gray)", "Fracture (Multistate)", "Death post fracture (Multistate)"),
col = c("black","black","red","blue","green","green"), lty = c(1,2,1,1,1,3), lwd = 2, bty = 'n', cex = 0.8)
title(main= "Men")
mtext("Difference in fracture incidence by competing risk models", line = 0, side = 3, outer = TRUE, cex = 2)
mean(wpps$sex); mean(wpps$age); mean(wpps$fnbmd); mean(wpps$falls_n); mean(wpps$prior_fx)
## [1] 0.6342669
## [1] 69.10359
## [1] 1.357313
## [1] 0.2674355
## [1] 0.1317957
subj.base.mean <- expand.grid(sex = 0.63, age = 69.1, fnbmd = 1.36, falls_n = 0.28, prior_fx = 0.13)
subj.base.mean
## sex age fnbmd falls_n prior_fx
## 1 0.63 69.1 1.36 0.28 0.13
# Conventional #
summary(cfit.con.f)
## Call:
## coxph(formula = Surv(kmfu_fx, Fx1st_sen) ~ sex + age + fnbmd +
## falls_n + prior_fx, data = wpps, id = StudyID)
##
## n= 1821, number of events= 505
##
## coef exp(coef) se(coef) z Pr(>|z|)
## sex 0.394651 1.483867 0.111300 3.546 0.000391 ***
## age 0.042794 1.043723 0.008007 5.345 9.07e-08 ***
## fnbmd 0.404080 1.497923 0.047510 8.505 < 2e-16 ***
## falls_n 0.009253 1.009296 0.075632 0.122 0.902632
## prior_fx 0.397371 1.487908 0.123750 3.211 0.001322 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex 1.484 0.6739 1.1930 1.846
## age 1.044 0.9581 1.0275 1.060
## fnbmd 1.498 0.6676 1.3647 1.644
## falls_n 1.009 0.9908 0.8702 1.171
## prior_fx 1.488 0.6721 1.1675 1.896
##
## Concordance= 0.693 (se = 0.013 )
## Likelihood ratio test= 221.9 on 5 df, p=<2e-16
## Wald test = 228.3 on 5 df, p=<2e-16
## Score (logrank) test = 235.9 on 5 df, p=<2e-16
con.fx.basem <- survfit(cfit.con.f, newdata = subj.base.mean)
summary(con.fx.basem, time = c(1,5,10,15,20,25))
## Call: survfit(formula = cfit.con.f, newdata = subj.base.mean)
##
## time n.risk n.event survival std.err lower 95% CI upper 95% CI
## 1 1758 43 0.982 0.00285 0.976 0.987
## 5 1326 145 0.908 0.00697 0.895 0.922
## 10 729 155 0.783 0.01196 0.759 0.806
## 15 313 94 0.642 0.01737 0.609 0.677
## 20 97 50 0.467 0.02654 0.418 0.522
## 25 32 14 0.347 0.03539 0.284 0.423
# Cause-specific (not needed as the 'CSC' was used) #
# Fine-Gray #
summary(fgfit.f)
## Call:
## coxph(formula = Surv(fgstart, fgstop, fgstatus) ~ sex + age +
## fnbmd + falls_n + prior_fx, data = fgdata.fx, weights = fgwt)
##
## n= 49711, number of events= 505
##
## coef exp(coef) se(coef) robust se z Pr(>|z|)
## sex 0.532712 1.703547 0.110046 0.104024 5.121 3.04e-07 ***
## age 0.011767 1.011836 0.007528 0.006885 1.709 0.08744 .
## fnbmd 0.365037 1.440567 0.044831 0.040265 9.066 < 2e-16 ***
## falls_n 0.103195 1.108708 0.074308 0.071336 1.447 0.14801
## prior_fx 0.338834 1.403311 0.122979 0.117573 2.882 0.00395 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex 1.704 0.5870 1.3893 2.089
## age 1.012 0.9883 0.9983 1.026
## fnbmd 1.441 0.6942 1.3313 1.559
## falls_n 1.109 0.9020 0.9640 1.275
## prior_fx 1.403 0.7126 1.1145 1.767
##
## Concordance= 0.683 (se = 0.012 )
## Likelihood ratio test= 176.2 on 5 df, p=<2e-16
## Wald test = 224.6 on 5 df, p=<2e-16
## Score (logrank) test = 177.7 on 5 df, p=<2e-16, Robust = 165.7 p=<2e-16
##
## (Note: the likelihood ratio and score tests assume independence of
## observations within a cluster, the Wald and robust score tests do not).
fg.fx.basem <- survfit(fgfit.f, newdata = subj.base.mean)
summary(fg.fx.basem, time = c(1,5,10,15,20,25))
## Call: survfit(formula = fgfit.f, newdata = subj.base.mean)
##
## time n.risk n.event survival std.err lower 95% CI upper 95% CI
## 1 1778 43 0.980 0.00301 0.974 0.986
## 5 1418 145 0.907 0.00679 0.894 0.921
## 10 729 155 0.800 0.01067 0.779 0.821
## 15 313 94 0.694 0.01442 0.666 0.723
## 20 162 50 0.579 0.01997 0.541 0.619
## 25 32 14 0.513 0.02462 0.467 0.563
# MSM #
summary(msmfit)
## Call:
## coxph(formula = Surv(tstart, tstop, event) ~ sex + age + fnbmd +
## falls_n + prior_fx, data = msm.data, id = StudyID)
##
## n= 2257, number of events= 789
##
## coef exp(coef) se(coef) robust se z Pr(>|z|)
## sex_1:2 0.484042 1.622620 0.121971 0.123186 3.929 8.52e-05 ***
## age_1:2 0.030720 1.031197 0.008691 0.009045 3.397 0.000682 ***
## fnbmd_1:2 0.402157 1.495046 0.050721 0.051157 7.861 3.80e-15 ***
## falls_n_1:2 0.025733 1.026067 0.081235 0.086838 0.296 0.766977
## prior_fx_1:2 0.370094 1.447871 0.133482 0.140989 2.625 0.008665 **
## sex_1:3 -0.731544 0.481165 0.131667 0.139269 -5.253 1.50e-07 ***
## age_1:3 0.127881 1.136418 0.010263 0.010593 12.073 < 2e-16 ***
## fnbmd_1:3 0.034614 1.035220 0.061108 0.070760 0.489 0.624722
## falls_n_1:3 -0.348446 0.705784 0.129952 0.128053 -2.721 0.006506 **
## prior_fx_1:3 0.014681 1.014789 0.205793 0.212689 0.069 0.944970
## sex_2:3 -1.170363 0.310254 0.275851 0.267189 -4.380 1.19e-05 ***
## age_2:3 0.157412 1.170478 0.021315 0.020866 7.544 4.56e-14 ***
## fnbmd_2:3 0.343225 1.409485 0.124269 0.126827 2.706 0.006805 **
## falls_n_2:3 -0.051889 0.949435 0.183594 0.188336 -0.276 0.782924
## prior_fx_2:3 0.145217 1.156291 0.300550 0.297771 0.488 0.625775
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## exp(coef) exp(-coef) lower .95 upper .95
## sex_1:2 1.6226 0.6163 1.2746 2.0657
## age_1:2 1.0312 0.9697 1.0131 1.0496
## fnbmd_1:2 1.4950 0.6689 1.3524 1.6527
## falls_n_1:2 1.0261 0.9746 0.8655 1.2164
## prior_fx_1:2 1.4479 0.6907 1.0983 1.9087
## sex_1:3 0.4812 2.0783 0.3662 0.6322
## age_1:3 1.1364 0.8800 1.1131 1.1603
## fnbmd_1:3 1.0352 0.9660 0.9012 1.1892
## falls_n_1:3 0.7058 1.4169 0.5491 0.9071
## prior_fx_1:3 1.0148 0.9854 0.6689 1.5396
## sex_2:3 0.3103 3.2232 0.1838 0.5238
## age_2:3 1.1705 0.8544 1.1236 1.2193
## fnbmd_2:3 1.4095 0.7095 1.0993 1.8072
## falls_n_2:3 0.9494 1.0533 0.6564 1.3733
## prior_fx_2:3 1.1563 0.8648 0.6451 2.0727
##
## Concordance= 0.711 (se = 0.01 )
## Likelihood ratio test= 459.4 on 15 df, p=<2e-16
## Wald test = 521.4 on 15 df, p=<2e-16
## Score (logrank) test = 501.8 on 15 df, p=<2e-16, Robust = 275.5 p=<2e-16
##
## (Note: the likelihood ratio and score tests assume independence of
## observations within a cluster, the Wald and robust score tests do not).
msm.basem <- survfit(msmfit, newdata = subj.base.mean)
summary(msm.basem, time = c(1,5,10,15,20,25))
## Call: survfit(formula = msmfit, newdata = subj.base.mean)
##
## data 1
## time n.risk n.event Pr((s0)) Pr(Fracture) Pr(Death)
## 1 1799 65 0.974 0.0184 0.00735
## 5 1452 236 0.871 0.0839 0.04522
## 10 863 244 0.712 0.1653 0.12300
## 15 414 135 0.547 0.2368 0.21614
## 20 143 74 0.359 0.2787 0.36196
## 25 52 28 0.239 0.1786 0.58211
wpp_val <- read.csv("C:\\Thach\\Research projects\\MSM and competing risk\\Data_Analysis\\wpp_s40.csv")
head(wpp_val)
## Fx1st_sen BMI_0 neuro_0 rheum_0 hypert_0 diabetes_0 respi_0 cancer_0 cvd_0
## 1 1 26.13 0 0 1 0 0 0 0
## 2 0 30.48 0 0 1 1 0 0 0
## 3 0 32.30 0 0 1 0 0 0 0
## 4 0 38.57 0 0 1 0 0 0 0
## 5 0 27.34 0 0 1 0 0 0 1
## 6 1 25.59 1 0 1 0 0 0 0
## prior_fx age StudyID sex falls_n death_sen fnbmd kmfu_fx kmfu_death
## 1 0 67.39 8 1 0 0 0.2833 19.789185 19.876797
## 2 0 64.55 27 1 0 0 1.1500 19.301848 19.301848
## 3 0 64.19 29 1 0 0 0.2083 2.603696 2.603696
## 4 0 60.76 32 1 0 0 0.3333 2.168378 2.168378
## 5 0 62.22 36 0 0 1 -0.9583 17.768652 17.768652
## 6 0 67.67 40 0 0 0 2.4583 12.854209 12.646133
## group fx_1y fx_5y fx_10y fx_15y fx_20y fx_25y
## 1 1 0 0 0 0 1 1
## 2 0 0 0 0 0 0 0
## 3 0 0 0 0 0 0 0
## 4 0 0 0 0 0 0 0
## 5 2 0 0 0 0 0 0
## 6 1 0 0 0 1 1 1
Conventional, FG and MSM: using baseline hazards and coefficients CS: using a ‘black box’ from CSC command
# Conventional
wpp_val$pifx_con = 0.39465*(wpp_val$sex - 0.63) + 0.04279*(wpp_val$age - 69.1) + 0.40408*(wpp_val$fnbmd - 1.36) + 0.00925*(wpp_val$falls_n - 0.28) + 0.3974*(wpp_val$prior_fx - 0.13);
wpp_val$riskfx_con1y = 1- 0.981673**exp(wpp_val$pifx_con)
wpp_val$riskfx_con5y = 1- 0.908361**exp(wpp_val$pifx_con)
wpp_val$riskfx_con10y = 1- 0.782545**exp(wpp_val$pifx_con)
wpp_val$riskfx_con15y = 1- 0.642094**exp(wpp_val$pifx_con)
wpp_val$riskfx_con20y = 1- 0.466764**exp(wpp_val$pifx_con)
wpp_val$riskfx_con25y = 1- 0.346552**exp(wpp_val$pifx_con)
# Cause-specific
CSC.risk <- predict(CSC.fit, newdata = wpp_val, times = c(1,5,10,15,20,25), cause = "Fracture")
CSC.dat <- data.frame(CSC.risk$absRisk)
# Fine-Gray
wpp_val$pifx_fg = 0.5327*(wpp_val$sex - 0.63) + 0.011767*(wpp_val$age - 69.1) + 0.36504*(wpp_val$fnbmd - 1.36) + 0.1032*(wpp_val$falls_n - 0.28) + 0.3388*(wpp_val$prior_fx - 0.13);
wpp_val$riskfx_fg1y = 1- 0.980345**exp(wpp_val$pifx_fg)
wpp_val$riskfx_fg5y = 1- 0.907297**exp(wpp_val$pifx_fg)
wpp_val$riskfx_fg10y = 1- 0.799797**exp(wpp_val$pifx_fg)
wpp_val$riskfx_fg15y = 1- 0.693884**exp(wpp_val$pifx_fg)
wpp_val$riskfx_fg20y = 1- 0.578737**exp(wpp_val$pifx_fg)
wpp_val$riskfx_fg25y = 1- 0.512648**exp(wpp_val$pifx_fg)
# Multistate
wpp_val$pifx_msm = 0.48404*(wpp_val$sex - 0.63) + 0.03072*(wpp_val$age - 69.1) + 0.40216*(wpp_val$fnbmd - 1.36) + 0.0257*(wpp_val$falls_n - 0.28) + 0.3701*(wpp_val$prior_fx - 0.13);
wpp_val$riskfx_msm1y = 1- (1- 0.0183764)**exp(wpp_val$pifx_msm)
wpp_val$riskfx_msm5y = 1- (1- 0.0839146)**exp(wpp_val$pifx_msm)
wpp_val$riskfx_msm10y = 1- (1- 0.1652715)**exp(wpp_val$pifx_msm)
wpp_val$riskfx_msm15y = 1- (1- 0.2367901)**exp(wpp_val$pifx_msm)
wpp_val$riskfx_msm20y = 1- (1- 0.2786909)**exp(wpp_val$pifx_msm)
wpp_val$riskfx_msm25y = 1- (1- 0.1785696)**exp(wpp_val$pifx_msm)
table.1v <- CreateTableOne(vars = Vars, strata = "group", data = wpp_val, factorVars = factorVars)
print(table.1v, nonnormal = c("kmfu_fx","kmfu_death"))
## Stratified by group
## 0 1
## n 554 259
## sex = 1 (%) 345 (62.3) 203 (78.4)
## age (mean (SD)) 68.08 (5.36) 69.81 (6.74)
## fnbmd (mean (SD)) 1.14 (1.17) 1.70 (1.06)
## falls_n (%)
## 0 457 (82.5) 187 (72.2)
## 1 66 (11.9) 51 (19.7)
## 2 31 ( 5.6) 21 ( 8.1)
## prior_fx = 1 (%) 59 (10.6) 50 (19.3)
## kmfu_fx (median [IQR]) 9.47 [5.68, 14.15] 7.21 [2.85, 12.49]
## kmfu_death (median [IQR]) 9.47 [5.68, 14.15] 12.68 [7.43, 17.15]
## BMI_0 (mean (SD)) 27.13 (4.43) 26.69 (3.57)
## cvd_0 = 1 (%) 175 (31.6) 99 (38.2)
## respi_0 = 1 (%) 52 ( 9.4) 29 (11.2)
## diabetes_0 = 1 (%) 76 (13.7) 25 ( 9.7)
## hypert_0 = 1 (%) 286 (51.6) 134 (51.7)
## cancer_0 = 1 (%) 44 ( 7.9) 28 (10.8)
## rheum_0 = 1 (%) 12 ( 2.2) 10 ( 3.9)
## neuro_0 = 1 (%) 40 ( 7.2) 21 ( 8.1)
## Stratified by group
## 2 p test
## n 122
## sex = 1 (%) 57 (46.7) <0.001
## age (mean (SD)) 72.64 (7.67) <0.001
## fnbmd (mean (SD)) 1.45 (1.48) <0.001
## falls_n (%) 0.004
## 0 102 (83.6)
## 1 10 ( 8.2)
## 2 10 ( 8.2)
## prior_fx = 1 (%) 19 (15.6) 0.003
## kmfu_fx (median [IQR]) 5.93 [2.34, 9.21] <0.001 nonnorm
## kmfu_death (median [IQR]) 5.93 [2.34, 9.21] <0.001 nonnorm
## BMI_0 (mean (SD)) 26.95 (1.40) 0.332
## cvd_0 = 1 (%) 64 (52.5) <0.001
## respi_0 = 1 (%) 16 (13.1) 0.416
## diabetes_0 = 1 (%) 18 (14.8) 0.207
## hypert_0 = 1 (%) 63 (51.6) 1.000
## cancer_0 = 1 (%) 11 ( 9.0) 0.407
## rheum_0 = 1 (%) 7 ( 5.7) 0.085
## neuro_0 = 1 (%) 6 ( 4.9) 0.529
windows(width = 16, height = 12)
par(mfrow=c(2,2), oma=c(0,0,2,0))
val.prob.ci.2(wpp_val$riskfx_con5y, wpp_val$fx_5y, pl = T, logistic.cal = F, g = 10,
xlab="Predicted risk", ylab="Observed risk", ylim = c(0, 0.45), xlim = c(0,0.45), cex.axis = .8, cex.lab = 1,
statloc = c(-0.01, 0.35), cex = .8)
## Call:
## val.prob.ci.2(p = wpp_val$riskfx_con5y, y = wpp_val$fx_5y, pl = T,
## logistic.cal = F, xlab = "Predicted risk", ylab = "Observed risk",
## xlim = c(0, 0.45), ylim = c(0, 0.45), g = 10, statloc = c(-0.01,
## 0.35), cex = 0.8, cex.axis = 0.8, cex.lab = 1)
##
## A 95% confidence interval is given for the calibration intercept, calibration slope and c-statistic.
##
## Dxy C (ROC) R2 D D:Chi-sq
## 4.430243e-01 7.215121e-01 1.198782e-01 6.049030e-02 5.755843e+01
## D:p U U:Chi-sq U:p Q
## 3.286260e-14 -1.794149e-03 3.224707e-01 8.510917e-01 6.228445e-02
## Brier Intercept Slope Emax Brier scaled
## 9.031487e-02 -6.019106e-02 9.835171e-01 2.353082e-02 7.073985e-02
## Eavg ECI
## 2.004853e-02 1.980804e-01
title(main= "A. Conventional Cox's PH model", adj = 0, cex.main = 1.4)
val.prob.ci.2(CSC.dat$X2, wpp_val$fx_5y, pl = T, logistic.cal = F, g = 10,
xlab="Predicted risk", ylab="Observed risk", ylim = c(0, 0.45), xlim = c(0,0.45), cex.axis = .8, cex.lab = 1,
statloc = c(-0.01, 0.35), cex = .8)
## Call:
## val.prob.ci.2(p = CSC.dat$X2, y = wpp_val$fx_5y, pl = T, logistic.cal = F,
## xlab = "Predicted risk", ylab = "Observed risk", xlim = c(0,
## 0.45), ylim = c(0, 0.45), g = 10, statloc = c(-0.01,
## 0.35), cex = 0.8, cex.axis = 0.8, cex.lab = 1)
##
## A 95% confidence interval is given for the calibration intercept, calibration slope and c-statistic.
##
## Dxy C (ROC) R2 D D:Chi-sq
## 4.473319e-01 7.236659e-01 1.218747e-01 6.154834e-02 5.854769e+01
## D:p U U:Chi-sq U:p Q
## 1.987299e-14 -1.455629e-03 6.389870e-01 7.265169e-01 6.300396e-02
## Brier Intercept Slope Emax Brier scaled
## 9.024284e-02 5.592022e-02 1.090645e+00 6.288579e-02 7.148100e-02
## Eavg ECI
## 1.621784e-02 9.848144e-02
title(main= "B. Cause-specific model", adj = 0, cex.main = 1.4)
val.prob.ci.2(wpp_val$riskfx_fg5y, wpp_val$fx_5y, pl = T, logistic.cal = F, g = 10,
xlab="Predicted risk", ylab="Observed risk", ylim = c(0, 0.45), xlim = c(0,0.45), cex.axis = .8, cex.lab = 1,
statloc = c(-0.01, 0.35), cex = .8)
## Call:
## val.prob.ci.2(p = wpp_val$riskfx_fg5y, y = wpp_val$fx_5y, pl = T,
## logistic.cal = F, xlab = "Predicted risk", ylab = "Observed risk",
## xlim = c(0, 0.45), ylim = c(0, 0.45), g = 10, statloc = c(-0.01,
## 0.35), cex = 0.8, cex.axis = 0.8, cex.lab = 1)
##
## A 95% confidence interval is given for the calibration intercept, calibration slope and c-statistic.
##
## Dxy C (ROC) R2 D D:Chi-sq
## 4.352565e-01 7.176282e-01 1.140713e-01 5.741938e-02 5.468712e+01
## D:p U U:Chi-sq U:p Q
## 1.413314e-13 -2.580716e-04 1.758703e+00 4.150520e-01 5.767745e-02
## Brier Intercept Slope Emax Brier scaled
## 9.087069e-02 3.526537e-03 1.229851e+00 1.203697e-01 6.502097e-02
## Eavg ECI
## 1.679280e-02 6.927981e-02
title(main= "C. Fine-Gray model", adj = 0, cex.main = 1.4)
val.prob.ci.2(wpp_val$riskfx_msm5y, wpp_val$fx_5y, pl = T, logistic.cal = F, g = 10,
xlab="Predicted risk", ylab="Observed risk", ylim = c(0, 0.45), xlim = c(0,0.45), cex.axis = .8, cex.lab = 1,
statloc = c(-0.01, 0.35), cex = .8, legendloc = c(0.2,0.1), cex.leg = .8)
## Call:
## val.prob.ci.2(p = wpp_val$riskfx_msm5y, y = wpp_val$fx_5y, pl = T,
## logistic.cal = F, xlab = "Predicted risk", ylab = "Observed risk",
## xlim = c(0, 0.45), ylim = c(0, 0.45), g = 10, legendloc = c(0.2,
## 0.1), statloc = c(-0.01, 0.35), cex = 0.8, cex.leg = 0.8,
## cex.axis = 0.8, cex.lab = 1)
##
## A 95% confidence interval is given for the calibration intercept, calibration slope and c-statistic.
##
## Dxy C (ROC) R2 D D:Chi-sq
## 4.459078e-01 7.229539e-01 1.203610e-01 6.074603e-02 5.779754e+01
## D:p U U:Chi-sq U:p Q
## 2.908784e-14 -1.451570e-03 6.427818e-01 7.251398e-01 6.219760e-02
## Brier Intercept Slope Emax Brier scaled
## 9.032284e-02 6.503964e-02 1.079130e+00 5.894907e-02 7.065784e-02
## Eavg ECI
## 1.712531e-02 1.148505e-01
title(main= "D. Multistate model", adj = 0, cex.main = 1.4)
mtext("Prediction of 5-year fracture risk", line = 0, side = 3, outer = TRUE, cex = 2)
windows(width = 16, height = 12)
par(mfrow=c(2,2), oma=c(0,0,2,0))
val.prob.ci.2(wpp_val$riskfx_con10y, wpp_val$fx_10y, pl = T, logistic.cal = F, g = 10,
xlab="Predicted risk", ylab="Observed risk", ylim = c(0, 0.8), xlim = c(0,0.8), cex.axis = .8, cex.lab = 1,
statloc = c(-0.02, 0.62), cex = .8, legendloc = c(0,0))
## Call:
## val.prob.ci.2(p = wpp_val$riskfx_con10y, y = wpp_val$fx_10y,
## pl = T, logistic.cal = F, xlab = "Predicted risk", ylab = "Observed risk",
## xlim = c(0, 0.8), ylim = c(0, 0.8), g = 10, legendloc = c(0,
## 0), statloc = c(-0.02, 0.62), cex = 0.8, cex.axis = 0.8,
## cex.lab = 1)
##
## A 95% confidence interval is given for the calibration intercept, calibration slope and c-statistic.
##
## Dxy C (ROC) R2 D D:Chi-sq
## 3.816175e-01 6.908087e-01 1.078817e-01 6.671796e-02 6.338130e+01
## D:p U U:Chi-sq U:p Q
## 1.665335e-15 4.126414e-02 4.058197e+01 1.540767e-09 2.545382e-02
## Brier Intercept Slope Emax Brier scaled
## 1.426678e-01 -5.153542e-01 7.517738e-01 2.278306e-01 2.295429e-02
## Eavg ECI
## 8.080606e-02 1.026543e+00
title(main= "A. Conventional Cox's PH model", adj = 0, cex.main = 1.4)
val.prob.ci.2(CSC.dat$X3, wpp_val$fx_10y, pl = T, logistic.cal = F, g = 10,
xlab="Predicted risk", ylab="Observed risk", ylim = c(0, 0.8), xlim = c(0,0.8), cex.axis = .8, cex.lab = 1,
statloc = c(-0.02, 0.62), cex = .8, legendloc = c(0,0))
## Call:
## val.prob.ci.2(p = CSC.dat$X3, y = wpp_val$fx_10y, pl = T, logistic.cal = F,
## xlab = "Predicted risk", ylab = "Observed risk", xlim = c(0,
## 0.8), ylim = c(0, 0.8), g = 10, legendloc = c(0, 0),
## statloc = c(-0.02, 0.62), cex = 0.8, cex.axis = 0.8, cex.lab = 1)
##
## A 95% confidence interval is given for the calibration intercept, calibration slope and c-statistic.
##
## Dxy C (ROC) R2 D D:Chi-sq
## 3.845003e-01 6.922501e-01 1.109204e-01 6.869552e-02 6.523031e+01
## D:p U U:Chi-sq U:p Q
## 6.661338e-16 -1.009903e-03 1.055741e+00 5.898598e-01 6.970542e-02
## Brier Intercept Slope Emax Brier scaled
## 1.348481e-01 -8.904794e-02 1.024066e+00 1.630391e-02 7.650677e-02
## Eavg ECI
## 2.138634e-02 9.658921e-02
title(main= "B. Cause-specific model", adj = 0, cex.main = 1.4)
val.prob.ci.2(wpp_val$riskfx_fg10y, wpp_val$fx_10y, pl = T, logistic.cal = F, g = 10,
xlab="Predicted risk", ylab="Observed risk", ylim = c(0, 0.8), xlim = c(0,0.8), cex.axis = .8, cex.lab = 1,
statloc = c(-0.02, 0.62), cex = .8, legendloc = c(0,0))
## Call:
## val.prob.ci.2(p = wpp_val$riskfx_fg10y, y = wpp_val$fx_10y, pl = T,
## logistic.cal = F, xlab = "Predicted risk", ylab = "Observed risk",
## xlim = c(0, 0.8), ylim = c(0, 0.8), g = 10, legendloc = c(0,
## 0), statloc = c(-0.02, 0.62), cex = 0.8, cex.axis = 0.8,
## cex.lab = 1)
##
## A 95% confidence interval is given for the calibration intercept, calibration slope and c-statistic.
##
## Dxy C (ROC) R2 D D:Chi-sq
## 3.816175e-01 6.908087e-01 1.094833e-01 6.775979e-02 6.435541e+01
## D:p U U:Chi-sq U:p Q
## 9.992007e-16 1.345834e-02 1.458355e+01 6.811177e-04 5.430145e-02
## Brier Intercept Slope Emax Brier scaled
## 1.372787e-01 -3.294245e-01 9.993744e-01 8.236295e-02 5.986099e-02
## Eavg ECI
## 5.656463e-02 4.301090e-01
title(main= "C. Fine-Gray model", adj = 0, cex.main = 1.4)
val.prob.ci.2(wpp_val$riskfx_msm10y, wpp_val$fx_10y, pl = T, logistic.cal = F, g = 10,
xlab="Predicted risk", ylab="Observed risk", ylim = c(0, 0.8), xlim = c(0,0.8), cex.axis = .8, cex.lab = 1,
statloc = c(-0.02, 0.62), cex = .8, legendloc = c(0.45,0.2), cex.leg = .8)
## Call:
## val.prob.ci.2(p = wpp_val$riskfx_msm10y, y = wpp_val$fx_10y,
## pl = T, logistic.cal = F, xlab = "Predicted risk", ylab = "Observed risk",
## xlim = c(0, 0.8), ylim = c(0, 0.8), g = 10, legendloc = c(0.45,
## 0.2), statloc = c(-0.02, 0.62), cex = 0.8, cex.leg = 0.8,
## cex.axis = 0.8, cex.lab = 1)
##
## A 95% confidence interval is given for the calibration intercept, calibration slope and c-statistic.
##
## Dxy C (ROC) R2 D D:Chi-sq
## 3.857458e-01 6.928729e-01 1.114422e-01 6.903546e-02 6.554816e+01
## D:p U U:Chi-sq U:p Q
## 5.551115e-16 1.192882e-03 3.115345e+00 2.106258e-01 6.784258e-02
## Brier Intercept Slope Emax Brier scaled
## 1.350592e-01 -1.286991e-01 8.827999e-01 8.454544e-02 7.506117e-02
## Eavg ECI
## 2.930845e-02 2.239376e-01
title(main= "D. Multistate model", adj = 0, cex.main = 1.4)
mtext("Prediction of 10-year fracture risk", line = 0, side = 3, outer = TRUE, cex = 2)