Rmarkdown template to generate this page can be found on Rmarkdown-Template.
library(ggplot2)
library(dplyr)
library(broom)
library(knitr)
library(tidyr)
library(survival)
library(survminer)
library(xgxr)
set.seed(123456)
#Use the lung dataset to create a fake exposure dataset
km_data <- lung %>%
mutate(fake_Cmax = ph.ecog + age/50 + sex + runif(nrow(lung)),
fake_AUC = ph.ecog*3 + (age/50)^sex + runif(nrow(lung))) %>%
filter(!is.na(fake_Cmax)) %>%
mutate(Cmax_quartile= cut(fake_Cmax,
breaks=quantile(fake_Cmax,c(0,.25,.5,.75,1)),
include.lowest=TRUE,
labels=paste0("Q",c(4,3,2,1))),
AUC_quartile = cut(fake_AUC,
breaks=quantile(fake_AUC,c(0,.25,.5,.75,1)),
include.lowest=TRUE,
labels=paste0("Q",c(4,3,2,1))),)
#these columns are required for your dataset
km_data <- km_data %>%
mutate(exposure = Cmax_quartile, #exposure quantile,
time = time, #time of the event (or censoring)
event = status) #status: there are a three options for this column (see ?Surv)
# a) 0 = censored (alive), 1 = dead (event)
# b) 1 = censored (alive), 2 = dead (event)
# c) 0 = right censored, 1 = event at time,
# 2 = left censored, 3 = interval censored.
km_data_Cmax_AUC <- km_data %>%
gather(NCAparam, NCAvalue, Cmax_quartile:AUC_quartile)
Time-to-event plots can be summarized by Kaplan-Meier plots and stratified by exposure quartile to give an overview of the dose-response. To see if there’s an effect on exposure vs response, look to see if there is separation between the quartiles. However note that it may be that there are factors that impact both exposure and response and so a more careful model-based analysis may be needed to formally assess any causal relationship, as described in the reference below.
Yang, Jun, et al. “The combination of exposure‐response and case‐control analyses in regulatory decision making.” The Journal of Clinical Pharmacology 53.2 (2013): 160-166.
km_fit <- survfit(Surv(time, status) ~ exposure, data = km_data, conf.int = 0.95)
gg <- ggsurvplot(km_fit, km_data, conf.int = TRUE, ggtheme = xgx_theme())
gg <- gg + xgx_scale_x_time_units(units_dataset = "day", units_plot = "year")
print(gg)
Using the ggsurvplot_facet
command, one can look at many
exposure metrics at once. Again, look for separation in the quartiles,
but be aware that something like a case-control analysis may be needed
to assess whether exposure causes reduced response or whether other
factors may affect both exposure and response.
km_fit_Cmax_AUC <- survfit(Surv(time, status) ~ NCAvalue, data = km_data_Cmax_AUC, conf.int = 0.95)
gg <- ggsurvplot_facet(km_fit_Cmax_AUC,
km_data_Cmax_AUC,
facet.by = "NCAparam",
conf.int = TRUE,
ggtheme = xgx_theme())
gg <- gg + xgx_scale_x_time_units(units_dataset = "day", units_plot = "year")
print(gg)
This plot can help in assessing the impact of a covariate (ECOG) on outcome.
Note, ph.ecog == 3
patient are removed from dataset
because there is only one patient with ECOG = 3 and this causes an error
when generating the confidence interval. This bug was reported to
the survminer developer and fixed in the github version.
km_data_noecog3 <- km_data %>% filter (ph.ecog != 3)
km_fit_ecog <- survfit(Surv(time, status) ~ ph.ecog,
data = km_data_noecog3 ,
conf.int = 0.95)
gg <- ggsurvplot_facet(km_fit_ecog,
km_data_noecog3,
facet.by = c("Cmax_quartile"),
conf.int = TRUE,
ggtheme = xgx_theme(),
legend.labs = paste0("ECOG=",sort(unique(km_data_noecog3$ph.ecog))))
gg <- gg + xgx_scale_x_time_units(units_dataset = "day", units_plot = "year")
print(gg)
In this data only 2 variables are available, so variable selection isn’t needed. If there are multiple variables, applying a variable selection approach (e.g. stepwiseAIC) would be advisable. Look for small p values or large hazard ratios to identify covariates that have a large effect.
km_cox <- coxph(Surv(time) ~ fake_AUC + fake_Cmax,
data =km_data)
km_cox_summary <- broom::tidy(km_cox) %>%
mutate_at(vars(-term),signif,2)
kable(km_cox_summary)
term | estimate | std.error | statistic | p.value |
---|---|---|---|---|
fake_AUC | 0.14 | 0.055 | 2.5 | 0.012 |
fake_Cmax | -0.16 | 0.130 | -1.2 | 0.210 |
sessionInfo()
## R version 4.1.0 (2021-05-18)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Red Hat Enterprise Linux Server 7.9 (Maipo)
##
## Matrix products: default
## BLAS/LAPACK: /CHBS/apps/EB/software/imkl/2019.1.144-gompi-2019a/compilers_and_libraries_2019.1.144/linux/mkl/lib/intel64_lin/libmkl_gf_lp64.so
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 LC_MONETARY=en_US.UTF-8
## [6] LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] survminer_0.4.9 ggpubr_0.4.0 survival_3.4-0 knitr_1.40 broom_1.0.1 caTools_1.18.2 DT_0.26 forcats_0.5.2 stringr_1.4.1
## [10] purrr_0.3.5 readr_2.1.3 tibble_3.1.8 tidyverse_1.3.2 xgxr_1.1.1 zoo_1.8-11 gridExtra_2.3 tidyr_1.2.1 dplyr_1.0.10
## [19] ggplot2_3.3.6
##
## loaded via a namespace (and not attached):
## [1] googledrive_2.0.0 colorspace_2.0-3 ggsignif_0.6.2 deldir_1.0-6 rio_0.5.27 ellipsis_0.3.2 class_7.3-19
## [8] htmlTable_2.2.1 markdown_1.2 base64enc_0.1-3 fs_1.5.2 gld_2.6.2 rstudioapi_0.14 proxy_0.4-26
## [15] farver_2.1.1 Deriv_4.1.3 fansi_1.0.3 mvtnorm_1.1-3 lubridate_1.8.0 xml2_1.3.3 codetools_0.2-18
## [22] splines_4.1.0 cachem_1.0.6 rootSolve_1.8.2.2 Formula_1.2-4 jsonlite_1.8.3 km.ci_0.5-2 binom_1.1-1
## [29] cluster_2.1.3 dbplyr_2.2.1 png_0.1-7 compiler_4.1.0 httr_1.4.4 backports_1.4.1 assertthat_0.2.1
## [36] Matrix_1.5-1 fastmap_1.1.0 gargle_1.2.1 cli_3.4.1 prettyunits_1.1.1 htmltools_0.5.3 tools_4.1.0
## [43] gtable_0.3.1 glue_1.6.2 lmom_2.8 Rcpp_1.0.9 carData_3.0-4 cellranger_1.1.0 jquerylib_0.1.4
## [50] vctrs_0.5.0 nlme_3.1-160 crosstalk_1.2.0 xfun_0.34 openxlsx_4.2.4 rvest_1.0.3 lifecycle_1.0.3
## [57] rstatix_0.7.0 googlesheets4_1.0.1 MASS_7.3-58.1 scales_1.2.1 hms_1.1.2 expm_0.999-6 RColorBrewer_1.1-3
## [64] curl_4.3.3 yaml_2.3.6 Exact_2.1 KMsurv_0.1-5 pander_0.6.4 sass_0.4.2 rpart_4.1.16
## [71] reshape_0.8.8 latticeExtra_0.6-30 stringi_1.7.8 highr_0.9 e1071_1.7-8 checkmate_2.1.0 zip_2.2.0
## [78] boot_1.3-28 rlang_1.0.6 pkgconfig_2.0.3 bitops_1.0-7 evaluate_0.17 lattice_0.20-45 htmlwidgets_1.5.4
## [85] labeling_0.4.2 tidyselect_1.2.0 GGally_2.1.2 plyr_1.8.7 magrittr_2.0.3 R6_2.5.1 DescTools_0.99.42
## [92] generics_0.1.3 Hmisc_4.7-0 DBI_1.1.3 pillar_1.8.1 haven_2.5.1 foreign_0.8-82 withr_2.5.0
## [99] mgcv_1.8-41 abind_1.4-5 RCurl_1.98-1.4 nnet_7.3-17 car_3.0-11 crayon_1.5.2 modelr_0.1.9
## [106] survMisc_0.5.5 interp_1.1-2 utf8_1.2.2 tzdb_0.3.0 rmarkdown_2.17 progress_1.2.2 jpeg_0.1-9
## [113] grid_4.1.0 readxl_1.4.1 minpack.lm_1.2-1 data.table_1.14.2 reprex_2.0.2 digest_0.6.30 xtable_1.8-4
## [120] munsell_0.5.0 bslib_0.4.0