CMHT01
Cochran-Mantel-Haenszel (CMH) Summary
Code
anl_01 <- adqs %>%
filter(PARAMCD == "FKSI-FWB" & AVISIT == "WEEK 1 DAY 8") %>%
mutate(is_rsp = PCHG > 15) %>%
mutate(ARM = relevel(ARM, ref = "A: Drug X")) %>%
var_relabel(ARM = "Description of Planned Arm") %>%
mutate(strata = interaction(STRATA1, STRATA2, drop = TRUE))
lyt_01 <- basic_table(show_colcounts = TRUE) %>%
split_cols_by(var = "ARM", ref_group = "A: Drug X") %>%
estimate_proportion(vars = "is_rsp", table_names = "est_prop") %>%
estimate_proportion_diff(
var_labels = "Unstratified Analysis",
vars = "is_rsp",
show_labels = "visible",
table_names = "est_prop_diff"
) %>%
test_proportion_diff(vars = "is_rsp", table_names = "test_prop") %>%
estimate_odds_ratio(vars = "is_rsp", table_names = "est_or") %>%
estimate_proportion_diff(
var_labels = "Stratified Analysis",
vars = "is_rsp",
show_labels = "visible",
method = "cmh",
variables = list(strata = "strata"),
table_names = "est_prop_diff_strat"
) %>%
test_proportion_diff(
vars = "is_rsp",
method = "cmh",
variables = list(strata = "strata"),
table_names = "test_prop_strat"
) %>%
estimate_odds_ratio(
vars = "is_rsp",
variables = list(strata = "strata", arm = "ARM"),
table_names = "est_or_strat"
)
result <- build_table(
lyt = lyt_01,
df = anl_01,
alt_counts_df = adsl
)
result
A: Drug X B: Placebo C: Combination
(N=134) (N=134) (N=132)
-------------------------------------------------------------------------------------------------
Responders 49 (36.6%) 51 (38.1%) 47 (35.6%)
95% CI (Wald, with correction) (28.0, 45.1) (29.5, 46.7) (27.1, 44.2)
Unstratified Analysis
Difference in Response rate (%) 1.5 -1.0
95% CI (Wald, with correction) (-10.8, 13.8) (-13.3, 11.3)
p-value (Chi-Squared Test) 0.8006 0.8704
Odds Ratio (95% CI) 1.07 (0.65 - 1.75) 0.96 (0.58 - 1.58)
Stratified Analysis
Difference in Response rate (%) 2.8 -1.5
95% CI (CMH, without correction) (-8.2, 13.8) (-13.0, 9.9)
p-value (Cochran-Mantel-Haenszel Test) 0.6397 0.7952
Odds Ratio (95% CI) 1.12 (0.68 - 1.83) 0.99 (0.60 - 1.64)
Code
anl_02 <- adqs %>%
filter(AVISIT == "WEEK 1 DAY 8") %>%
mutate(is_rsp = PCHG > 15) %>%
mutate(PARAM = droplevels(PARAM)) %>%
mutate(ARM = relevel(ARM, ref = "A: Drug X")) %>%
var_relabel(ARM = "Description of Planned Arm") %>%
mutate(strata = interaction(STRATA1, STRATA2, drop = TRUE))
var_labels(anl_02)["PARAM"] <- "Parameter"
split_fun <- drop_split_levels
lyt_02 <- basic_table(show_colcounts = TRUE) %>%
split_cols_by(var = "ARM", ref_group = "A: Drug X") %>%
split_rows_by(
var = "PARAM",
split_fun = split_fun,
label_pos = "topleft",
split_label = obj_label(anl_02$PARAM)
) %>%
estimate_proportion(vars = "is_rsp", table_names = "est_prop") %>%
estimate_proportion_diff(
var_labels = "Unstratified Analysis",
vars = "is_rsp",
show_labels = "visible",
table_names = "est_prop_diff"
) %>%
test_proportion_diff(vars = "is_rsp", table_names = "test_prop") %>%
estimate_odds_ratio(vars = "is_rsp", table_names = "est_or") %>%
estimate_proportion_diff(
var_labels = "Stratified Analysis",
vars = "is_rsp",
show_labels = "visible",
method = "cmh",
variables = list(strata = "strata"),
table_names = "est_prop_diff_strat"
) %>%
test_proportion_diff(
vars = "is_rsp",
method = "cmh",
variables = list(strata = "strata"),
table_names = "test_prop_strat"
) %>%
estimate_odds_ratio(
vars = "is_rsp",
variables = list(strata = "strata", arm = "ARM"),
table_names = "est_or_strat"
)
result <- build_table(
lyt = lyt_02,
df = anl_02,
alt_counts_df = adsl
)
result
A: Drug X B: Placebo C: Combination
Parameter (N=134) (N=134) (N=132)
---------------------------------------------------------------------------------------------------
BFI All Questions
Responders 57 (42.5%) 65 (48.5%) 50 (37.9%)
95% CI (Wald, with correction) (33.8, 51.3) (39.7, 57.3) (29.2, 46.5)
Unstratified Analysis
Difference in Response rate (%) 6.0 -4.7
95% CI (Wald, with correction) (-6.7, 18.6) (-17.2, 7.9)
p-value (Chi-Squared Test) 0.3264 0.4385
Odds Ratio (95% CI) 1.27 (0.79 - 2.06) 0.82 (0.50 - 1.35)
Stratified Analysis
Difference in Response rate (%) 6.7 -5.1
95% CI (CMH, without correction) (-5.0, 18.4) (-16.8, 6.6)
p-value (Cochran-Mantel-Haenszel Test) 0.2781 0.4056
Odds Ratio (95% CI) 1.30 (0.80 - 2.11) 0.80 (0.49 - 1.32)
Fatigue Interference
Responders 66 (49.3%) 50 (37.3%) 48 (36.4%)
95% CI (Wald, with correction) (40.4, 58.1) (28.8, 45.9) (27.8, 44.9)
Unstratified Analysis
Difference in Response rate (%) -11.9 -12.9
95% CI (Wald, with correction) (-24.5, 0.6) (-25.4, -0.3)
p-value (Chi-Squared Test) 0.0485 0.0337
Odds Ratio (95% CI) 0.61 (0.38 - 1.00) 0.59 (0.36 - 0.96)
Stratified Analysis
Difference in Response rate (%) -12.0 -13.3
95% CI (CMH, without correction) (-23.7, -0.2) (-24.9, -1.6)
p-value (Cochran-Mantel-Haenszel Test) 0.0518 0.0303
Odds Ratio (95% CI) 0.61 (0.37 - 0.99) 0.58 (0.36 - 0.96)
FKSI-19 All Questions
Responders 60 (44.8%) 57 (42.5%) 68 (51.5%)
95% CI (Wald, with correction) (36.0, 53.6) (33.8, 51.3) (42.6, 60.4)
Unstratified Analysis
Difference in Response rate (%) -2.2 6.7
95% CI (Wald, with correction) (-14.9, 10.4) (-6.0, 19.5)
p-value (Chi-Squared Test) 0.7118 0.2714
Odds Ratio (95% CI) 0.91 (0.56 - 1.48) 1.31 (0.81 - 2.12)
Stratified Analysis
Difference in Response rate (%) -2.8 5.6
95% CI (CMH, without correction) (-14.3, 8.8) (-6.2, 17.4)
p-value (Cochran-Mantel-Haenszel Test) 0.6442 0.3683
Odds Ratio (95% CI) 0.90 (0.56 - 1.47) 1.26 (0.77 - 2.04)
Function/Well-Being (GF1,GF3,GF7)
Responders 49 (36.6%) 51 (38.1%) 47 (35.6%)
95% CI (Wald, with correction) (28.0, 45.1) (29.5, 46.7) (27.1, 44.2)
Unstratified Analysis
Difference in Response rate (%) 1.5 -1.0
95% CI (Wald, with correction) (-10.8, 13.8) (-13.3, 11.3)
p-value (Chi-Squared Test) 0.8006 0.8704
Odds Ratio (95% CI) 1.07 (0.65 - 1.75) 0.96 (0.58 - 1.58)
Stratified Analysis
Difference in Response rate (%) 2.8 -1.5
95% CI (CMH, without correction) (-8.2, 13.8) (-13.0, 9.9)
p-value (Cochran-Mantel-Haenszel Test) 0.6397 0.7952
Odds Ratio (95% CI) 1.12 (0.68 - 1.83) 0.99 (0.60 - 1.64)
Treatment Side Effects (GP2,C5,GP5)
Responders 62 (46.3%) 49 (36.6%) 51 (38.6%)
95% CI (Wald, with correction) (37.5, 55.1) (28.0, 45.1) (30.0, 47.3)
Unstratified Analysis
Difference in Response rate (%) -9.7 -7.6
95% CI (Wald, with correction) (-22.2, 2.8) (-20.2, 5.0)
p-value (Chi-Squared Test) 0.1069 0.2080
Odds Ratio (95% CI) 0.67 (0.41 - 1.09) 0.73 (0.45 - 1.19)
Stratified Analysis
Difference in Response rate (%) -9.6 -7.1
95% CI (CMH, without correction) (-21.0, 1.8) (-18.8, 4.6)
p-value (Cochran-Mantel-Haenszel Test) 0.1168 0.2426
Odds Ratio (95% CI) 0.67 (0.41 - 1.10) 0.73 (0.45 - 1.19)
Code
library(teal.modules.clinical)
## Data reproducible code
data <- teal_data()
data <- within(data, {
ADSL <- random.cdisc.data::cadsl
ADRS <- random.cdisc.data::cadrs
})
datanames <- c("ADSL", "ADRS")
datanames(data) <- datanames
join_keys(data) <- default_cdisc_join_keys[datanames]
## Reusable Configuration For Modules
ADRS <- data[["ADRS"]]
arm_ref_comp <- list(
ARMCD = list(ref = "ARM B", comp = c("ARM A", "ARM C")),
ARM = list(ref = "B: Placebo", comp = c("A: Drug X", "C: Combination"))
)
## Setup App
app <- init(
data = data,
modules = modules(
tm_t_binary_outcome(
label = "Responders",
dataname = "ADRS",
paramcd = choices_selected(
choices = value_choices(ADRS, "PARAMCD", "PARAM"),
selected = "BESRSPI"
),
arm_var = choices_selected(
choices = variable_choices(ADRS, c("ARM", "ARMCD", "ACTARMCD")),
selected = "ARM"
),
arm_ref_comp = arm_ref_comp,
strata_var = choices_selected(
choices = variable_choices(ADRS, c("SEX", "BMRKR2")),
select = NULL
)
)
)
)
shinyApp(app$ui, app$server)
Experimental use!
shinylive
allow you to modify to run shiny
application entirely in the web browser. Modify the code below and click re-run the app to see the results. The performance is slighly worse and some of the features (e.g. downloading) might not work at all.
#| standalone: true
#| viewerHeight: 800
#| components: [viewer, editor]
#| layout: vertical
# -- WEBR HELPERS --
options(webr_pkg_repos = c("r-universe" = "https://pharmaverse.r-universe.dev", getOption("webr_pkg_repos")))
if (packageVersion("webr") < "0.3.0") {
.e <- as.environment("webr_shims")
.e[["library"]] <- function(pkg, ...) {
package <- as.character(substitute(pkg))
if (length(find.package(package, quiet = TRUE)) == 0) {
webr::install(package)
}
base::library(package, character.only = TRUE, ...)
}
}
# -- APP CODE --
library(teal.modules.clinical)
## Data reproducible code
data <- teal_data()
data <- within(data, {
ADSL <- random.cdisc.data::cadsl
ADRS <- random.cdisc.data::cadrs
})
datanames <- c("ADSL", "ADRS")
datanames(data) <- datanames
join_keys(data) <- default_cdisc_join_keys[datanames]
## Reusable Configuration For Modules
ADRS <- data[["ADRS"]]
arm_ref_comp <- list(
ARMCD = list(ref = "ARM B", comp = c("ARM A", "ARM C")),
ARM = list(ref = "B: Placebo", comp = c("A: Drug X", "C: Combination"))
)
## Setup App
app <- init(
data = data,
modules = modules(
tm_t_binary_outcome(
label = "Responders",
dataname = "ADRS",
paramcd = choices_selected(
choices = value_choices(ADRS, "PARAMCD", "PARAM"),
selected = "BESRSPI"
),
arm_var = choices_selected(
choices = variable_choices(ADRS, c("ARM", "ARMCD", "ACTARMCD")),
selected = "ARM"
),
arm_ref_comp = arm_ref_comp,
strata_var = choices_selected(
choices = variable_choices(ADRS, c("SEX", "BMRKR2")),
select = NULL
)
)
)
)
shinyApp(app$ui, app$server)
Timestamp
Session Info
R version 4.4.0 (2024-04-24)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 22.04.4 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/libopenblasp-r0.3.20.so; LAPACK version 3.10.0
locale:
[1] C
time zone: Etc/UTC
tzcode source: system (glibc)
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] teal.modules.clinical_0.9.1.9005 teal.transform_0.5.0.9005
[3] teal_0.15.2.9036 teal.slice_0.5.1.9002
[5] teal.data_0.6.0.9002 teal.code_0.5.0.9005
[7] shiny_1.8.1.1 dplyr_1.1.4
[9] tern_0.9.4.9007 rtables_0.6.7.9002
[11] magrittr_2.0.3 formatters_0.5.6.9004
loaded via a namespace (and not attached):
[1] tidyselect_1.2.1 fastmap_1.1.1
[3] random.cdisc.data_0.3.15.9003 TH.data_1.1-2
[5] webshot2_0.1.1 shinyjs_2.1.0
[7] promises_1.3.0 digest_0.6.35
[9] estimability_1.5 mime_0.12
[11] tern.gee_0.1.3.9006 lifecycle_1.0.4
[13] survival_3.6-4 processx_3.8.4
[15] compiler_4.4.0 sass_0.4.9
[17] rlang_1.1.3 tools_4.4.0
[19] utf8_1.2.4 yaml_2.3.8
[21] knitr_1.46 htmlwidgets_1.6.4
[23] multcomp_1.4-25 websocket_1.4.1
[25] withr_3.0.0 purrr_1.0.2
[27] shinyWidgets_0.8.6 geepack_1.3.10
[29] grid_4.4.0 fansi_1.0.6
[31] teal.logger_0.2.0.9002 xtable_1.8-4
[33] colorspace_2.1-0 ggplot2_3.5.1
[35] emmeans_1.10.1 scales_1.3.0
[37] MASS_7.3-60.2 cli_3.6.2
[39] mvtnorm_1.2-4 rmarkdown_2.26
[41] generics_0.1.3 cachem_1.0.8
[43] chromote_0.2.0 stringr_1.5.1
[45] splines_4.4.0 formatR_1.14
[47] vctrs_0.6.5 webshot_0.5.5
[49] Matrix_1.7-0 sandwich_3.1-0
[51] jsonlite_1.8.8 callr_3.7.6
[53] teal.widgets_0.4.2.9011 testthat_3.2.1.1
[55] fontawesome_0.5.2 jquerylib_0.1.4
[57] tidyr_1.3.1 glue_1.7.0
[59] codetools_0.2-20 ps_1.7.6
[61] stringi_1.8.3 gtable_0.3.5
[63] later_1.3.2 shinycssloaders_1.0.0
[65] munsell_0.5.1 tibble_3.2.1
[67] logger_0.3.0 pillar_1.9.0
[69] htmltools_0.5.8.1 brio_1.1.5
[71] R6_2.5.1 Rdpack_2.6
[73] evaluate_0.23 lattice_0.22-6
[75] rbibutils_2.2.16 backports_1.4.1
[77] memoise_2.0.1 broom_1.0.5
[79] teal.reporter_0.3.1.9005 bslib_0.7.0
[81] httpuv_1.6.15 Rcpp_1.0.12
[83] shinyvalidate_0.1.3 coda_0.19-4.1
[85] nlme_3.1-164 checkmate_2.3.1
[87] xfun_0.43 zoo_1.8-12
[89] forcats_1.0.0 pkgconfig_2.0.3
.lock
file
Download the .lock
file and use renv::restore()
on it to recreate environment used to generate this website.
Code
parent_file_path <- knitr::current_input(dir = TRUE)
book_root_dir <- parent_file_path
while (!file.exists(file.path(book_root_dir, "_quarto.yml"))) book_root_dir <- dirname(book_root_dir)
lock_path <- file.path(
"../../assets/www/lock",
paste0(
gsub(
file.path(book_root_dir, ""),
"",
gsub(
"\\.rmarkdown$",
"",
knitr::current_input(dir = TRUE)
)
),
".lock"
)
)
withr::with_options(
list(renv.verbose = FALSE),
renv::snapshot(parent_file_path, lockfile = lock_path, prompt = FALSE, force = TRUE)
)