The {crane} package supplements the {gtsummary} package to ease the process of creating Roche clinical trial tables. {gtsummary} is a general framework for building tables, and {crane} utilizes the frame work and exports functions meant to simplify the creation of summary tables in pharmaceutical industry.
The {crane} package includes wrapper functions for {gtsummary} functions to make it easier to apply common pharma-specific modifications to table formats. For example, demographics tables which use certain variables and formatting conventions as a default.
When the crane package is loaded into your R session, a couple of things occur.
crane::theme_gtsummary_roche()
. This theme changes a few
default behaviors for {gtsummary} tables; for example, all p-values are
rounded with label_roche_pvalue()
, and tables are printed
with {flextable} instead of {gt}. See the function’s help file for
details.
library(crane)
#> Loading required package: gtsummary
theme_gtsummary_roche()
#> Setting theme "Roche"
While all Roche tables can be created using {gtsummary}, for some tables the code can become long. In these cases, adding a new function to {crane} is warranted.
For example, our standard demographics table can be created with
gtsummary::tbl_summary()
. But for such a common table, the
code is somewhat long, and we therefore created
crane::tbl_roche_summary()
.
To create the Roche standard demographics table, we simple call:
cards::ADSL |>
tbl_roche_summary(
by = ARM,
include = c(AGE, RACE),
nonmissing = "always"
)
Placebo |
Xanomeline High Dose |
Xanomeline Low Dose |
|
---|---|---|---|
Age |
|||
n |
86 |
84 |
84 |
Mean (SD) |
75 (9) |
74 (8) |
76 (8) |
Median |
76 |
76 |
78 |
Min - Max |
52 - 89 |
56 - 88 |
51 - 88 |
Race |
|||
n |
86 |
84 |
84 |
AMERICAN INDIAN OR ALASKA NATIVE |
0 |
1 (1.2%) |
0 |
BLACK OR AFRICAN AMERICAN |
8 (9.3%) |
9 (10.7%) |
6 (7.1%) |
WHITE |
78 (90.7%) |
74 (88.1%) |
78 (92.9%) |
To create this table with gtsummary::tbl_summary()
, we’d
need the following code. As some of these steps are not the most
straightforward, we created the tbl_roche_summary()
wrapper.
cards::ADSL |>
tbl_summary(
by = ARM,
include = c(AGE, RACE),
type = list(AGE = "continuous2"),
statistic = list(AGE = c("{mean} ({sd})", "{median}", "{min} - {max}")),
digits = all_categorical() ~ list(p = 1),
missing = "always",
missing_stat = "{N_nonmiss}",
missing_text = "n"
) |>
# remove default footnote
remove_footnote_header(columns = everything()) |>
# remove the default "Characteristic" header
modify_header(label = "") |>
# convert "0 (0.0%)" to "0"
gtsummary::modify_post_fmt_fun(
fmt_fun = ~ifelse(. == "0 (0.0%)", "0", .),
columns = all_stat_cols()
) |>
# sort the missing row to just below the header row
modify_table_body(
function(x) {
x |>
dplyr::mutate(
.by = "variable",
dplyr::across(dplyr::everything(), ~ .[order(row_type != "label", row_type != "missing")])
)
}
)
Another case where we may create helper functions in {crane}, is when the table can only be created in {gtsummary} using an ARD-first approach. Generally, creating an ARD of all results in a summary table, then creating then table is more cumbersome. In these cumbersome cases, a new function in {crane} is warranted.