insightsengineering / teal.modules.clinical

Provides teal modules for the standard clinical trials outputs
https://insightsengineering.github.io/teal.modules.clinical/
Other
32 stars 17 forks source link

[Bug]: Error in tm_t_coxreg when no covariates are selected #832

Closed mthbretscher closed 1 year ago

mthbretscher commented 1 year ago

What happened?

When starting a tm_t_coxreg module with no covarIates selected (which should be the default option for my use case) , then an error occurs.

The following code reproduces this error (example from ?tm_t_coxreg without covariates at startup):

adsl <- tmc_ex_adsl
adtte <- tmc_ex_adtte
arm_ref_comp <- list(
  ACTARMCD = list(
    ref = "ARM B",
    comp = c("ARM A", "ARM C")
  ),
  ARM = list(
    ref = "B: Placebo",
    comp = c("A: Drug X", "C: Combination")
  )
)

app <- init(
  data = cdisc_data(
    cdisc_dataset("ADSL", adsl),
    cdisc_dataset("ADTTE", adtte)
  ),
  modules = modules(
    tm_t_coxreg(
      label = "Cox Reg.",
      dataname = "ADTTE",
      arm_var = choices_selected(c("ARM", "ARMCD", "ACTARMCD"), "ARM"),
      arm_ref_comp = arm_ref_comp,
      paramcd = choices_selected(
        value_choices(adtte, "PARAMCD", "PARAM"), "OS"
      ),
      strata_var = choices_selected(
        c("COUNTRY", "STRATA1", "STRATA2"), "STRATA1"
      ),
      cov_var = choices_selected(
        c("AGE", "BMRKR1", "BMRKR2", "REGION1"), NULL
      ),
      multivariate = TRUE
    )
  )
)
if (interactive()) {
  shinyApp(app$ui, app$server)
}

Looking at "Show R code" (see "relevant log output" below) we found that only this line of code is responsible (without any involvement of the dataset yet):

lyt <- rtables::basic_table(title = "Multi-Variable Cox Regression for OS", subtitles = "Stratified by STRATA1", main_footer = c("p-value method for Coxph (Hazard Ratio): wald", "Ties for Coxph (Hazard Ratio): exact")) %>%
   rtables::append_topleft("OS") %>%
   summarize_coxreg(variables = list(time = "AVAL", event = "event", arm = "ARM", covariates = NULL, strata = "STRATA1"), control = list(pval_method = "wald", ties = "exact", conf_level = 0.95, interaction = FALSE), multivar = TRUE, .stats = c(
     "hr",
     "ci", "pval"
   ))

While the error is only caught deep down in the calling hierarchy in a function of the rtables package, the error can easily be prevented by not passing covariates = NULL to summarize_coxreg, like so:

lyt <- rtables::basic_table(title = "Multi-Variable Cox Regression for OS", subtitles = "Stratified by STRATA1", main_footer = c("p-value method for Coxph (Hazard Ratio): wald", "Ties for Coxph (Hazard Ratio): exact")) %>%
   rtables::append_topleft("OS") %>%
   summarize_coxreg(variables = list(time = "AVAL", event = "event", arm = "ARM", strata = "STRATA1"), control = list(pval_method = "wald", ties = "exact", conf_level = 0.95, interaction = FALSE), multivar = TRUE, .stats = c(
     "hr",
     "ci", "pval"
   ))

sessionInfo()

> sessionInfo()
R version 4.2.2 Patched (2022-11-10 r83330)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.6 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/liblapack.so.3

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8       
 [4] LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
[10] LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] teal.modules.clinical_0.8.16 tern_0.9.0                   rtables_0.6.3               
 [4] formatters_0.5.2             teal_0.14.0                  teal.transform_0.4.0        
 [7] magrittr_2.0.3               teal.slice_0.4.0             teal.data_0.3.0             
[10] shiny_1.7.4                 

loaded via a namespace (and not attached):
 [1] sass_0.4.5            tidyr_1.3.0           jsonlite_1.8.4        splines_4.2.2        
 [5] carData_3.0-5         R.utils_2.12.2        bslib_0.4.2           Rdpack_2.4           
 [9] assertthat_0.2.1      teal.code_0.4.1       tern.gee_0.1.0.9002   yaml_2.3.7           
[13] pillar_1.8.1          backports_1.4.1       lattice_0.20-45       glue_1.6.2           
[17] teal.widgets_0.4.0    digest_0.6.31         promises_1.2.0.1      rbibutils_2.2.13     
[21] checkmate_2.1.0       colorspace_2.1-0      sandwich_3.0-2        R.oo_1.25.0          
[25] shinycssloaders_1.0.0 htmltools_0.5.4       httpuv_1.6.9          Matrix_1.5-3         
[29] pkgconfig_2.0.3       broom_1.0.3           logger_0.2.2          purrr_1.0.1          
[33] xtable_1.8-4          mvtnorm_1.1-3         scales_1.2.1          fontawesome_0.5.0    
[37] later_1.3.0           emmeans_1.8.4-1       tibble_3.1.8          styler_1.9.0         
[41] car_3.1-1             generics_0.1.3        ggplot2_3.4.1         ellipsis_0.3.2       
[45] shinyvalidate_0.1.2   TH.data_1.1-2         cachem_1.0.6          withr_2.5.0          
[49] shinyjs_2.1.0         geepack_1.3.9         cli_3.6.0             crayon_1.5.2         
[53] survival_3.5-3        mime_0.12             evaluate_0.20         memoise_2.0.1        
[57] estimability_1.4.1    R.methodsS3_1.8.2     fansi_1.0.4           R.cache_0.16.0       
[61] nlme_3.1-162          MASS_7.3-58.2         forcats_1.0.0         teal.reporter_0.2.1  
[65] rsconnect_0.8.29      tools_4.2.2           lifecycle_1.0.3       multcomp_1.4-23      
[69] stringr_1.5.0         munsell_0.5.0         compiler_4.2.2        jquerylib_0.1.4      
[73] rlang_1.1.1           grid_4.2.2            rstudioapi_0.14       shinyWidgets_0.7.6   
[77] rmarkdown_2.20        gtable_0.3.1          codetools_0.2-19      teal.logger_0.1.3    
[81] abind_1.4-5           R6_2.5.1              zoo_1.8-11            knitr_1.42           
[85] dplyr_1.1.0           fastmap_1.1.0         utf8_1.2.3            stringi_1.7.12       
[89] Rcpp_1.0.10           vctrs_0.5.2           xfun_0.37             tidyselect_1.2.0     
[93] coda_0.19-4

Relevant log output

Error: invalid class “MultiVarSplit” object: 1: invalid object for slot "var_labels" in class "MultiVarSplit": got class "NULL", should be or extend class "character"
invalid class “MultiVarSplit” object: 2: invalid object for slot "var_names" in class "MultiVarSplit": got class "NULL", should be or extend class "character" 
 when evaluating qenv code:
anl <- ANL %>%
  dplyr::filter(ARM %in% c("B: Placebo", "A: Drug X", "C: Combination")) %>%
  dplyr::mutate(ARM = stats::relevel(ARM, ref = "B: Placebo")) %>%
  dplyr::mutate(ARM = droplevels(ARM)) %>%
  dplyr::mutate(event = 1 - CNSR) %>%
  df_explicit_na(na_level = "")
lyt <- rtables::basic_table(title = "Multi-Variable Cox Regression for OS", subtitles = "Stratified by STRATA1", main_footer = c("p-value method for Coxph (Hazard Ratio): wald", "Ties for Coxph (Hazard Ratio): exact")) %>%
  rtables::append_topleft("OS") %>%
  summarize_coxreg(variables = list(time = "AVAL", event = "event", arm = "ARM", covariates = NULL, strata = "STRATA1"), control = list(pval_method = "wald", ties = "exact", conf_level = 0.95, interaction = FALSE), multivar = TRUE, .stats = c(
    "hr",
    "ci", "pval"
  ))
result <- rtables::build_table(lyt = lyt, df = anl)
result

trace: 
 library(shiny)
 library(teal.data)
 library(teal.slice)
 library(magrittr)
 library(teal.transform)
 library(teal)
 library(formatters)
 library(rtables)
 library(tern)
 library(teal.modules.clinical)
 message("Preprocessing is empty")
 message(paste("Reproducibility of data import and preprocessing was not explicitly checked", " ('check = FALSE' is set). Contact app developer if this is an issue.\n"))
 stopifnot(rlang::hash(ADSL) == "a5ae18b41288b967988d7c260b5fb4f6")
 stopifnot(rlang::hash(ADTTE) == "ebf4eda6b6c9de9c2c52ec25e0fc400f")
 ADTTE <- dplyr::inner_join(x = ADTTE, y = ADSL[, c("STUDYID", "USUBJID"), drop = FALSE], by = c("STUDYID", "USUBJID"))
 ANL_1 <- ADSL %>% dplyr::select(STUDYID, USUBJID, ARM, STRATA1)
 ANL_2 <- ADTTE %>%
   dplyr::filter(PARAMCD == "OS") %>%
   dplyr::select(STUDYID, USUBJID, PARAMCD)
 ANL_3 <- ADTTE %>% dplyr::select(STUDYID, USUBJID, PARAMCD, AVAL, CNSR)
 ANL <- ANL_1
 ANL <- dplyr::inner_join(ANL, ANL_2, by = c("STUDYID", "USUBJID"))
 ANL <- dplyr::inner_join(ANL, ANL_3, by = c("STUDYID", "USUBJID", "PARAMCD"))
 ANL <- ANL %>% teal.data::col_relabel(ARM = "Description of Planned Arm", PARAMCD = "Parameter Code", STRATA1 = "Stratification Factor 1", AVAL = "Analysis Value", CNSR = "Censor")
 anl <- ANL %>%
   dplyr::filter(ARM %in% c("B: Placebo", "A: Drug X", "C: Combination")) %>%
   dplyr::mutate(ARM = stats::relevel(ARM, ref = "B: Placebo")) %>%
   dplyr::mutate(ARM = droplevels(ARM)) %>%
   dplyr::mutate(event = 1 - CNSR) %>%
   df_explicit_na(na_level = "")
 lyt <- rtables::basic_table(title = "Multi-Variable Cox Regression for OS", subtitles = "Stratified by STRATA1", main_footer = c("p-value method for Coxph (Hazard Ratio): wald", "Ties for Coxph (Hazard Ratio): exact")) %>%
   rtables::append_topleft("OS") %>%
   summarize_coxreg(variables = list(time = "AVAL", event = "event", arm = "ARM", covariates = NULL, strata = "STRATA1"), control = list(pval_method = "wald", ties = "exact", conf_level = 0.95, interaction = FALSE), multivar = TRUE, .stats = c(
     "hr",
     "ci", "pval"
   ))
 result <- rtables::build_table(lyt = lyt, df = anl)
 result

Code of Conduct

Contribution Guidelines

Security Policy

mhallal1 commented 1 year ago

Tagging @donyunardi to transfer it to the core dev team. Thanks.

lcd2yyz commented 1 year ago

Hi @edelarua Is this related to https://github.com/insightsengineering/teal.modules.clinical/issues/830? Would the SME team also able to take care of this?

edelarua commented 1 year ago

Would the SME team also able to take care of this?

@lcd2yyz I can take this issue!