skip_on_cran()
skip_if_not(is_pkg_installed(c("cardx", "survival"), reference_pkg = "gtsummary"))
t1_summary <- trial |>
dplyr::filter(trt == "Drug A") |>
select(age, response, death) |>
tbl_summary() |>
modify_header(stat_0 ~ "**Statistic**")
t2_summary <- trial |>
dplyr::filter(trt == "Drug B") |>
select(age, response, death) |>
tbl_summary() |>
modify_header(stat_0 ~ "**Statistic**")
t1_regression <- glm(response ~ trt, trial, family = binomial) |>
tbl_regression(
exponentiate = TRUE,
label = list("trt" ~ "Treatment (unadjusted)")
)
t2_regression <- glm(response ~ trt + grade + stage + marker, trial, family = binomial) |>
tbl_regression(
include = "trt",
exponentiate = TRUE,
label = list("trt" ~ "Treatment (adjusted)")
)
t1_survival <- survival::coxph(survival::Surv(ttdeath, death) ~ trt, trial) |>
tbl_regression(
exponentiate = TRUE,
label = list("trt" ~ "Treatment (unadjusted)")
)
t2_survival <- survival::coxph(survival::Surv(ttdeath, death) ~ trt + grade + stage + marker, trial) |>
tbl_regression(
include = "trt",
exponentiate = TRUE,
label = list("trt" ~ "Treatment (adjusted)")
)
merge_row1 <- tbl_merge(list(t1_regression, t1_survival), tab_spanner = c("Tumor Response", "Death"))
merge_row2 <- tbl_merge(list(t2_regression, t2_survival))
test_that("tbl_stack works with standard use", {
expect_silent(
tbl <- tbl_stack(list(t1_summary, t2_summary), group_header = c("Drug A", "Drug B"))
)
# no error if list input is named
expect_silent(
tbl <- tbl_stack(list(t1 = t1_summary, t2 = t2_summary), group_header = c("Drug A", "Drug B"))
)
# correct number of rows after stacking
expect_equal(
nrow(tbl$table_body),
nrow(t1_summary$table_body) + nrow(t2_summary$table_body)
)
# correct ordering of stacked tables
expect_equal(tbl$tbls$t1$table_body, t1_summary$table_body)
expect_equal(tbl$tbls$t2$table_body, t2_summary$table_body)
# correct group headers
expect_equal(
tbl$table_body$groupname_col |> unique(),
c("Drug A", "Drug B")
)
expect_equal(
tbl$table_body$tbl_id1,
c(rep(1, 5), rep(2, 5))
)
# footnotes stacked correctly
expect_equal(
tbl$table_styling$footnote,
rbind(t1_summary$table_styling$footnote, t2_summary$table_styling$footnote)
)
# indentation values stacked correctly
expect_equal(
tbl$table_styling$indent |>
dplyr::select(-rows),
rbind(t1_summary$table_styling$indent, t2_summary$table_styling$indent) |>
dplyr::select(-rows)
)
})
test_that("tbl_stack(quiet) works", {
t1 <- t1_summary |>
modify_header(stat_0 ~ "**Statistic**")
t2 <- t2_summary |>
modify_header(stat_0 ~ "Replaced label")
expect_silent(tbl <- tbl_stack(list(t1, t2), quiet = TRUE))
expect_equal(
tbl |> as_tibble() |> names(),
c("**Characteristic**", "**Statistic**")
)
})
test_that("tbl_stack works with no group header", {
expect_silent(tbl <- tbl_stack(list(t1_summary, t2_summary)))
expect_true(!"groupname_col" %in% names(tbl$table_body))
expect_equal(
tbl$table_body$tbl_id1,
c(rep(1, 5), rep(2, 5))
)
})
test_that("tbl_stack works with a single table", {
expect_silent(tbl <- tbl_stack(list(t1_summary)))
# tbls has length 1
expect_equal(length(tbl$tbls), 1)
# table_body unchanged except for added id column
expect_equal(
tbl$table_body,
t1_summary$table_body |>
dplyr::mutate(tbl_id1 = 1L, .before = variable)
)
})
test_that("tbl_stack works with tbl_regression objects", {
expect_silent(
tbl <- tbl_stack(list(t1_regression, t2_regression), group_header = c("Group 1", "Group 2"))
)
# correct number of rows after stacking
expect_equal(
nrow(tbl$table_body),
nrow(t1_regression$table_body) + nrow(t2_regression$table_body)
)
# correct ordering of stacked tables
expect_equal(tbl$tbls[[1]]$table_body, t1_regression$table_body)
expect_equal(tbl$tbls[[2]]$table_body, t2_regression$table_body)
# correct group headers
expect_equal(
tbl$table_body$groupname_col |> unique(),
c("Group 1", "Group 2")
)
expect_equal(
tbl$table_body$tbl_id1,
c(rep(1, 3), rep(2, 3))
)
# footnote abbreviations stacked correctly
expect_equal(
tbl$table_styling$footnote_abbrev,
rbind(t1_regression$table_styling$footnote_abbrev, t2_regression$table_styling$footnote_abbrev)
)
})
test_that("tbl_stack works with tbl_merge objects", {
expect_silent(
tbl <- tbl_stack(list(merge_row1, merge_row2), quiet = TRUE)
)
# correct number of rows after stacking
expect_equal(
nrow(tbl$table_body),
nrow(merge_row1$table_body) + nrow(merge_row2$table_body)
)
# correct ordering of stacked tables
expect_equal(tbl$tbls[[1]]$table_body, merge_row1$table_body)
expect_equal(tbl$tbls[[2]]$table_body, merge_row2$table_body)
})
test_that("tbl_stack works with tbl_merge objects", {
expect_silent(
tbl <- tbl_stack(list(merge_row1, merge_row2), quiet = TRUE)
)
# correct number of rows after stacking
expect_equal(
nrow(tbl$table_body),
nrow(merge_row1$table_body) + nrow(merge_row2$table_body)
)
# correct ordering of stacked tables
expect_equal(tbl$tbls[[1]]$table_body, merge_row1$table_body)
expect_equal(tbl$tbls[[2]]$table_body, merge_row2$table_body)
})
test_that("tbl_stack works with formatting functions", {
t1 <- t1_regression |>
modify_fmt_fun(
p.value ~ function(x) style_pvalue(x, digits = 3),
rows = variable == "trt"
) |>
modify_fmt_fun(
estimate ~ function(x) style_ratio(x, digits = 4, decimal.mark = ",")
)
t2 <- t2_regression |>
modify_fmt_fun(
estimate ~ function(x) style_ratio(x, digits = 2, decimal.mark = "..")
)
expect_silent(tbl <- tbl_stack(list(t1, t2)))
expect_equal(
tbl |>
as_tibble(col_labels = FALSE) |>
dplyr::pull(estimate),
c(NA, NA, "1,2148", NA, NA, "1..48")
)
expect_equal(
tbl |>
as_tibble(col_labels = FALSE) |>
dplyr::pull(p.value),
c(NA, NA, "0.531", NA, NA, "0.2")
)
})
test_that("tbl_stack works with missing symbols", {
t1 <- t1_summary |>
modify_table_body(
~ .x |> mutate(stat_0 = NA_character_)
) |>
modify_table_styling(stat_0, rows = !is.na(label), missing_symbol = "n / a")
t2 <- t2_summary |>
modify_table_body(
~ .x |> mutate(stat_0 = NA_character_)
)
expect_silent(tbl <- tbl_stack(list(t1, t2)))
expect_equal(
tbl$table_styling$fmt_missing |>
dplyr::select(-rows),
rbind(t1$table_styling$fmt_missing, t2$table_styling$fmt_missing) |>
dplyr::select(-rows)
)
# missing symbol in first table only
expect_equal(
tbl |>
as_tibble(col_labels = FALSE, fmt_missing = TRUE) |>
dplyr::pull(stat_0),
c(rep("n / a", 5), rep(NA, 5))
)
t2 <- t2 |>
modify_table_styling(stat_0, rows = !is.na(label), missing_symbol = "miss")
expect_silent(tbl <- tbl_stack(list(t1, t2)))
# different missing symbol in each stacked table
expect_equal(
tbl |>
as_tibble(col_labels = FALSE, fmt_missing = TRUE) |>
dplyr::pull(stat_0),
c(rep("n / a", 5), rep("miss", 5))
)
expect_equal(
tbl$table_styling$fmt_missing |>
dplyr::select(-rows),
rbind(t2$table_styling$fmt_missing, t1$table_styling$fmt_missing) |>
dplyr::select(-rows)
)
})
test_that("tbl_stack returns expected message when unique column names are present", {
t1 <- t1_summary |>
modify_header(stat_0 ~ "**Statistic**")
t2 <- t2_summary |>
modify_header(stat_0 ~ "Replaced label")
expect_message(
tbl_stack(list(t1, t2)),
"Column headers among stacked tables differ"
)
})
test_that("tbl_stack() can stack tbl that have been previosly stacked", {
t1 <- trial |> tbl_summary(include = age, missing = "no")
t2 <- tbl_stack(list(t1, t1))
expect_silent(t3 <- tbl_stack(list(t1, t2)))
t4 <- glm(response ~ trt + grade + age, trial, family = binomial) %>%
tbl_regression(exponentiate = TRUE)
t5 <- survival::coxph(survival::Surv(ttdeath, death) ~ trt + grade + age, trial) %>%
tbl_regression(exponentiate = TRUE)
expect_error(t6 <- tbl_stack(tbls = list(t4, t5)), NA)
})
test_that("tbl_stack throws expected errors", {
# input must be a list
expect_snapshot(
tbl_stack(t1_summary, t2_summary),
error = TRUE
)
# must pass acceptable objects
expect_snapshot(
tbl_stack(list(mtcars)),
error = TRUE
)
# correct group header length
expect_snapshot(
tbl_stack(tbls = list(t1_summary, t2_summary), group_header = c("Table")),
error = TRUE
)
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.