Introduction to the Analysis Results Standard and {cards}
Introduction to the {cardx} Package and ARD Extras
ARD to Tables with {gtsummary} and {tfrmt}
Metadata-driven table formatting
Easily create new and modify existing tables
Input: ARD with raw, numeric values ({cards}!)
Output: Formatted table via {gt}
You can export the table to a variety of formats using gt::gt_save()
Demographics Table | |||
---|---|---|---|
Placebo N = xx |
Low Dose N = xx |
High Dose N = xx |
|
Age (y) | |||
Mean | xxx.x | xxx.x | xxx.x |
SD | xxx.xx | xxx.xx | xxx.xx |
Median | xxx.x | xxx.x | xxx.x |
Min | xxx.x | xxx.x | xxx.x |
Max | xxx.x | xxx.x | xxx.x |
<65 yrs | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) |
65-80 yrs | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) |
>80 yrs | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) |
Sex | |||
Male | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) |
Female | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) |
Baseline BMI | |||
Mean | xxx.x | xxx.x | xxx.x |
SD | xxx.xx | xxx.xx | xxx.xx |
Median | xxx.x | xxx.x | xxx.x |
Min | xxx.x | xxx.x | xxx.x |
Max | xxx.x | xxx.x | xxx.x |
<25 | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) |
25-<30 | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) |
>=30 | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) |
Demographics Table | |||
---|---|---|---|
Placebo N = 86 |
Low Dose N = 84 |
High Dose N = 84 |
|
Age (y) | |||
Mean | 75.2 | 75.7 | 74.4 |
SD | 8.59 | 8.29 | 7.89 |
Median | 76.0 | 77.5 | 76.0 |
Min | 52.0 | 51.0 | 56.0 |
Max | 89.0 | 88.0 | 88.0 |
<65 yrs | 14 (16.3 %) | 8 ( 9.5 %) | 11 (13.1 %) |
65-80 yrs | 42 (48.8 %) | 47 (56.0 %) | 55 (65.5 %) |
>80 yrs | 30 (34.9 %) | 29 (34.5 %) | 18 (21.4 %) |
Sex | |||
Male | 33 (38.4 %) | 34 (40.5 %) | 44 (52.4 %) |
Female | 53 (61.6 %) | 50 (59.5 %) | 40 (47.6 %) |
Baseline BMI | |||
Mean | 23.6 | 25.1 | 25.3 |
SD | 3.67 | 4.27 | 4.16 |
Median | 23.4 | 24.3 | 24.8 |
Min | 15.1 | 17.7 | 13.7 |
Max | 33.3 | 40.1 | 34.5 |
<25 | 59 (68.6 %) | 47 (56.0 %) | 44 (52.4 %) |
25-<30 | 21 (24.4 %) | 27 (32.1 %) | 28 (33.3 %) |
>=30 | 6 ( 7.0 %) | 10 (11.9 %) | 12 (14.3 %) |
Demographics Table | |||
---|---|---|---|
Safety Population | |||
High Dose (N = 84) |
Low Dose (N = 84) |
Placebo (N = 86) |
|
Age (y) | |||
Mean | 74.4 | 75.7 | 75.2 |
SD | 7.89 | 8.29 | 8.59 |
Median | 76.0 | 77.5 | 76.0 |
Min | 56.0 | 51.0 | 52.0 |
Max | 88.0 | 88.0 | 89.0 |
<65 yrs | 11 (13.1 %) | 8 ( 9.5 %) | 14 (16.3 %) |
65-80 yrs | 55 (65.5 %) | 47 (56.0 %) | 42 (48.8 %) |
>80 yrs | 18 (21.4 %) | 29 (34.5 %) | 30 (34.9 %) |
Sex | |||
Male | 44 (52.4 %) | 34 (40.5 %) | 33 (38.4 %) |
Female | 40 (47.6 %) | 50 (59.5 %) | 53 (61.6 %) |
Data collected at Screening Visit |
Organization standards can be capture as templates
With layering, teams can customize only the bits that need changing
# create a template as a function
tfrmt_demog_ta <- function(tfrmt_obj){
tfrmt_demog_ta <- tfrmt(
# define the formatting specific to the therapeutic area
)
layer_tfrmt(x = tfrmt_obj, y = tfrmt_demog_ta)
}
# Layering multiple templates
tfrmt_demog_org() |>
tfrmt_demog_ta() |>
print_to_gt(
.data = demog_data
)
Organization standards can be capture as templates
With layering, teams can customize only the bits that need changing
# create a template as a function
tfrmt_demog_study <- function(tfrmt_obj){
tfrmt_demog_study <- tfrmt(
# define the formatting specific to the study
)
layer_tfrmt(x = tfrmt_obj, y = tfrmt_demog_study)
}
# Layering multiple templates
tfrmt_demog_org() |>
tfrmt_demog_ta() |>
tfrmt_demog_study() |>
print_to_gt(
.data = demog_data
)
{
"group": ["rowlbl1", "grp"],
"label": ["rowlbl2"],
"param": ["param"],
"value": ["value"],
"column": ["column"],
"title": ["Demographics Table"],
"body_plan": [
{
"group_val": [".default"],
"label_val": [".default"],
"param_val": ["n", "pct"],
"frmt_combine": {
"expression": ["{n} {pct}"],
"frmt_ls": {
"n": {
"frmt": {
"expression": ["xxx"],
"missing": {},
"scientific": {},
"transform": {}
}
},
"pct": {
"frmt_when": {
"frmt_ls": {
"==100": [""],
"==0": [""],
"TRUE": {
"frmt": {
"expression": ["(xx.x %)"],
"missing": {},
"scientific": {},
"transform": {}
}
}
},
"missing": {}
}
}
},
"missing": {}
}
},
{
"group_val": [".default"],
"label_val": ["n"],
"param_val": [".default"],
"frmt": {
"expression": ["xxx"],
"missing": {},
"scientific": {},
"transform": {}
}
},
{
"group_val": [".default"],
"label_val": ["Mean", "Median", "Min", "Max"],
"param_val": [".default"],
"frmt": {
"expression": ["xxx.x"],
"missing": {},
"scientific": {},
"transform": {}
}
},
{
"group_val": [".default"],
"label_val": ["SD"],
"param_val": [".default"],
"frmt": {
"expression": ["xxx.xx"],
"missing": {},
"scientific": {},
"transform": {}
}
}
],
"col_style_plan": [
{
"cols": [
["Placebo"],
["Low Dose"],
["High Dose"]
],
"align": [".", ",", " "],
"type": ["char"],
"width": {}
},
{
"cols": [
["rowlbl1"],
["rowlbl2"]
],
"align": ["left"],
"type": ["char"],
"width": {}
}
],
"col_plan": {
"col_plan": {
"dots": [
["-grp"],
["-starts_with(\"ord\")"]
],
".drop": [false]
}
},
"sorting_cols": ["ord1", "ord2"],
"big_n": {
"param_val": ["bigN"],
"n_frmt": {
"expression": ["<br>N = xx"],
"missing": {},
"scientific": {},
"transform": {}
},
"by_page": [false]
}
}
Create a language-agnostic JSON file
Load JSON back into R and recreate the table with json_to_tfrmt()
{cards} includes a helper function rename_ard_columns()
to transform native {cards} output to display-ready data
library(cards)
library(tfrmt)
my_ard <- pharmaverseadam::adsl |>
dplyr::filter(SAFFL=="Y") |>
ard_categorical(
by = TRT01A,
variables = c("AGEGR1","SEX")
) |>
rename_ard_columns(columns = all_ard_groups(),
unlist = c("variable_level", "stat")) |>
dplyr::select(-c(fmt_fn, warning, error)) |>
dplyr::filter(stat_name %in% c("n","p")) |>
dplyr::select(-c(context, stat_label))
tfrmt(
group = variable,
label = variable_level ,
column = TRT01A,
param = stat_name,
value = stat,
body_plan = body_plan(
frmt_structure(group_val = ".default",
label_val = ".default",
frmt_combine("{n} ({p}%)",
n = frmt("xx"),
p = frmt("xx",
transform = ~.*100)))
)
) |>
print_to_gt(my_ard)|>
gt_style_slides()|>
gt::tab_options(
table.font.size = 15
)
Placebo | Xanomeline High Dose | Xanomeline Low Dose | |
---|---|---|---|
AGEGR1 | |||
>64 | 72 (84%) | 61 (85%) | 88 (92%) |
18-64 | 14 (16%) | 11 (15%) | 8 ( 8%) |
SEX | |||
F | 53 (62%) | 35 (49%) | 55 (57%) |
M | 33 (38%) | 37 (51%) | 41 (43%) |
Point-and-click interface for {tfrmt}
Ability to create new or modify existing display
Eases learning curve for new users
Empowers non-programmers
Introduction to the Analysis Results Standard and {cards}
Introduction to the {cardx} Package and ARD Extras
ARD to Tables with {gtsummary} and {tfrmt}
{gtsummary}: https://www.danieldsjoberg.com/gtsummary/
{tfrmtbuilder}: https://gsk-biostatistics.github.io/tfrmtbuilder/