I need to create a special table and I created it separately by 2 parts, because each of part need to use different denominator. I think if the structure of 2 table trees are same, rbind function should work.
In my dummy code "tbl_recipe1" and "tbl_recipe2" are used N_col as denominator and the structure of table trees are same, but N_col is different.
When I combined those 2 tables together, there is an error.
I know there may be some limitations when we use rbind function to combine 2 tables. I'm not very familiar to use tern and rtables packages. Do you have any suggestions to generate this special table?
library(random.cdisc.data)
library(dplyr)
library(rtables)
library(haven)
library(purrr)
library(stringr)
library(tern)
library(forcats)
library(formatters)
adsl_cdisc1 <- random.cdisc.data::cadsl
adex_cdisc1 <- random.cdisc.data::cadex
adsl_cdisc2 <- dplyr::filter(adsl_cdisc1, SAFFL == "Y") |>
dplyr::select(USUBJID, TRT01A) |>
dplyr::mutate(
TRT01A = forcats::fct_inorder(TRT01A)
)
adex_cdisc2 <- dplyr::select(
adex_cdisc1, USUBJID, SAFFL, STRATA1, AVISIT) |>
dplyr::left_join(adsl_cdisc2, by = "USUBJID") |>
dplyr::mutate(
EXP = dplyr::case_when(
!is.na(AVISIT) ~ "Number of exposed participants",
TRUE ~ NA_character_
),
STRA = dplyr::case_when(
STRATA1 == "B" ~ "Number of records with STRATA1 = B by visit",
TRUE ~ NA_character_
),
SORT = paste(USUBJID, AVISIT)
) |>
dplyr::filter(SAFFL == "Y", !is.na(AVISIT))
adex_cdisc3 <- dplyr::filter(adex_cdisc1, SAFFL == "Y") |>
dplyr::select(USUBJID, AVISIT) |>
dplyr::right_join(adsl_cdisc2, by = "USUBJID") |>
dplyr::mutate(
SORT = paste(USUBJID, AVISIT)
) |>
distinct(SORT, TRT01A)
tbl_recipe1 <- basic_table() |>
add_colcounts() |>
split_cols_by("TRT01A") |>
count_occurrences("EXP",
id = "USUBJID",
.stats = "count_fraction"
) |>
rtables::build_table(adex_cdisc2, alt_counts_df = adsl_cdisc2)
tbl_recipe2 <- basic_table() |>
add_colcounts() |>
split_cols_by("TRT01A") |>
count_occurrences("STRA",
id = "SORT",
.stats = "count_fraction"
) |>
rtables::build_table(adex_cdisc2, alt_counts_df = adex_cdisc3)
tbl <- rbind(
tbl_recipe1,
rtables::rrow(""),
tbl_recipe2
)
The issue that prevents your two tables from being row-bound is that each table uses a different dataset for alt_counts_df
in build_table()
. This means that the N
values are not the same in both tables, as you can see in the table headers of the screenshots you provided. When using rbind()
with two rtables, the column header structures must match exactly.
You can resolve this error in your table by adding the following line of code after generating both tables but before calling rbind()
:
col_info(tbl_recipe2) <- col_info(tbl_recipe1)
This will overwrite the non-matching column information of tbl_recipe2
with the column information of tbl_recipe1
so that both match, with the N
values from tbl_recipe1
displayed in the joint table header, but the percentages in the table may not make sense.
Using the example you provided:
library(tern)
adsl_cdisc1 <- random.cdisc.data::cadsl
adex_cdisc1 <- random.cdisc.data::cadex
adsl_cdisc2 <- dplyr::filter(adsl_cdisc1, SAFFL == "Y") |>
dplyr::select(USUBJID, TRT01A) |>
dplyr::mutate(TRT01A = forcats::fct_inorder(TRT01A))
adex_cdisc2 <- dplyr::select(
adex_cdisc1, USUBJID, SAFFL, STRATA1, AVISIT) |>
dplyr::left_join(adsl_cdisc2, by = "USUBJID") |>
dplyr::mutate(SORT = paste(USUBJID, AVISIT)) |>
dplyr::filter(SAFFL == "Y", !is.na(AVISIT))
adex_cdisc3 <- dplyr::filter(adex_cdisc1, SAFFL == "Y") |>
dplyr::select(USUBJID, AVISIT) |>
dplyr::right_join(adsl_cdisc2, by = "USUBJID") |>
dplyr::mutate(SORT = paste(USUBJID, AVISIT)) |>
dplyr::distinct(SORT, TRT01A)
tbl_recipe1 <- basic_table() |>
split_cols_by("TRT01A", show_colcounts = TRUE) |>
summarize_num_patients(
"USUBJID",
.stats = "unique",
.labels = "Number of exposed participants"
) |>
build_table(adex_cdisc2, alt_counts_df = adsl_cdisc2)
tbl_recipe2 <- basic_table() |>
split_cols_by("TRT01A", show_colcounts = TRUE) |>
count_patients_with_event(
vars = "SORT",
filters = c(STRATA1 = "B"),
.labels = c(count_fraction = "Number of records with STRATA1 = B by visit"),
denom = "N_col"
) |>
build_table(adex_cdisc2, alt_counts_df = adex_cdisc3)
col_info(tbl_recipe2) <- col_info(tbl_recipe1)
tbl <- rbind(
tbl_recipe1,
rrow(""),
tbl_recipe2
)
tbl
#> A: Drug X C: Combination B: Placebo
#> (N=134) (N=132) (N=134)
#> ————————————————————————————————————————————————————————————————————————————————————————
#> Number of exposed participants 134 (100%) 132 (100%) 134 (100%)
#>
#> Number of records with STRATA1 = B by visit 329 (30.7%) 301 (28.5%) 315 (29.4%)
Created on 2024-11-21 with reprex v2.1.1