Demography Table
For this demography table we are going to use
data_demog
, an example analysis results dataset found in
the package, which is based on the CDISC pilot data. This dataset has
two different row label columns, rowlbl1
and
rowlbl2
because we are building a table with group and row
labels. There are also two order columns which will be used to set the
row order of the output. There is a single column to define our table’s
columns (multiple column columns are used when there is column
spanning). Finally there is a param column, a value column and an
additional grouping column, grp
, which we can use for more
complex formatting.
#> # A tibble: 6 × 8
#> # Groups: rowlbl1 [1]
#> rowlbl1 rowlbl2 param grp ord1 ord2 column value
#> <chr> <chr> <chr> <chr> <dbl> <dbl> <chr> <dbl>
#> 1 Age (y) n n cont 1 1 Placebo 86
#> 2 Age (y) n n cont 1 1 Xanomeline Low Dose 84
#> 3 Age (y) n n cont 1 1 Xanomeline High Dose 84
#> 4 Age (y) n n cont 1 1 Total 254
#> 5 Age (y) n p cont 1 1 p-value 0.593
#> 6 Age (y) Mean Mean cont 1 2 Placebo 75.2
The mock we are going to match looks like this:
Placebo | Xanomeline Low Dose | Xanomeline High Dose | Total | p-value | ||
---|---|---|---|---|---|---|
Age (y) | n | xxx | xxx | xxx | xxx | x.xxx |
Mean | xxx.x | xxx.x | xxx.x | xxx.x | ||
SD | xxx.xx | xxx.xx | xxx.xx | xxx.xx | ||
Median | xxx.x | xxx.x | xxx.x | xxx.x | ||
Min | xxx.x | xxx.x | xxx.x | xxx.x | ||
Max | xxx.x | xxx.x | xxx.x | xxx.x | ||
<65 yrs | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | x.xxx | |
65-80 yrs | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
>80 yrs | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
Sex | n | xxx | xxx | xxx | xxx | x.xxx |
Male | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
Female | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
Race (Origin) | n | xxx | xxx | xxx | xxx | x.xxx |
Caucasian | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
African Descent | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
Hispanic | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
Other | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
MMSE | n | xxx | xxx | xxx | xxx | x.xxx |
Mean | xxx.x | xxx.x | xxx.x | xxx.x | ||
SD | xxx.xx | xxx.xx | xxx.xx | xxx.xx | ||
Median | xxx.x | xxx.x | xxx.x | xxx.x | ||
Min | xxx.x | xxx.x | xxx.x | xxx.x | ||
Max | xxx.x | xxx.x | xxx.x | xxx.x | ||
Duration of disease | n | xxx | xxx | xxx | xxx | x.xxx |
Mean | xxx.x | xxx.x | xxx.x | xxx.x | ||
SD | xxx.xx | xxx.xx | xxx.xx | xxx.xx | ||
Median | xxx.x | xxx.x | xxx.x | xxx.x | ||
Min | xxx.x | xxx.x | xxx.x | xxx.x | ||
Max | xxx.x | xxx.x | xxx.x | xxx.x | ||
<12 months | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | x.xxx | |
>=12 months | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
Years of education | n | xxx | xxx | xxx | xxx | x.xxx |
Mean | xxx.x | xxx.x | xxx.x | xxx.x | ||
SD | xxx.xx | xxx.xx | xxx.xx | xxx.xx | ||
Median | xxx.x | xxx.x | xxx.x | xxx.x | ||
Min | xxx.x | xxx.x | xxx.x | xxx.x | ||
Max | xxx.x | xxx.x | xxx.x | xxx.x | ||
Baseline weight(kg) | n | xxx | xxx | xxx | xxx | x.xxx |
Mean | xxx.x | xxx.x | xxx.x | xxx.x | ||
SD | xxx.xx | xxx.xx | xxx.xx | xxx.xx | ||
Median | xxx.x | xxx.x | xxx.x | xxx.x | ||
Min | xxx.x | xxx.x | xxx.x | xxx.x | ||
Max | xxx.x | xxx.x | xxx.x | xxx.x | ||
Baseline height(cm) | n | xxx | xxx | xxx | xxx | x.xxx |
Mean | xxx.x | xxx.x | xxx.x | xxx.x | ||
SD | xxx.xx | xxx.xx | xxx.xx | xxx.xx | ||
Median | xxx.x | xxx.x | xxx.x | xxx.x | ||
Min | xxx.x | xxx.x | xxx.x | xxx.x | ||
Max | xxx.x | xxx.x | xxx.x | xxx.x | ||
Baseline BMI | n | xxx | xxx | xxx | xxx | x.xxx |
Mean | xxx.x | xxx.x | xxx.x | xxx.x | ||
SD | xxx.xx | xxx.xx | xxx.xx | xxx.xx | ||
Median | xxx.x | xxx.x | xxx.x | xxx.x | ||
Min | xxx.x | xxx.x | xxx.x | xxx.x | ||
Max | xxx.x | xxx.x | xxx.x | xxx.x | ||
<25 | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | x.xxx | |
25-<30 | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
>=30 | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | xxx (xx.x %) | ||
For this table, we have three columns for each of the treatment groups, a total column for all groups combined, and a p-value column. The table also contains a mix of categorical and continuous analysis.
The first thing we are going to do when building out the
tfrmt
is specify all our columns
tfrmt(
# specify columns in the data
group = c(rowlbl1,grp),
label = rowlbl2,
column = column,
param = param,
value = value,
sorting_cols = c(ord1, ord2)) %>%
print_to_gt(data_demog) %>%
tab_options(
container.width = 900
)
ord1 | ord2 | Placebo | Xanomeline Low Dose | Xanomeline High Dose | Total | p-value | |
---|---|---|---|---|---|---|---|
Age (y) | |||||||
cont | |||||||
n | 1 | 1 | 86 | 84 | 84 | 254 | 0.593435775283097 |
Mean | 1 | 2 | 75.2093023255814 | 75.6666666666667 | 74.3809523809524 | 75.0866141732283 | NA |
SD | 1 | 3 | 8.59016712714193 | 8.28605059954093 | 7.88609384869824 | 8.24623389621606 | NA |
Median | 1 | 4 | 76 | 77.5 | 76 | 77 | NA |
Min | 1 | 5 | 52 | 51 | 56 | 51 | NA |
Max | 1 | 6 | 89 | 88 | 88 | 89 | NA |
cat | |||||||
<65 yrs | 1 | 7 | 14, 16.2790697674419 | 8, 9.52380952380952 | 11, 13.0952380952381 | 33, 12.992125984252 | 0.143917025502502 |
65-80 yrs | 1 | 8 | 42, 48.8372093023256 | 47, 55.9523809523809 | 55, 65.4761904761905 | 144, 56.6929133858268 | NA |
>80 yrs | 1 | 9 | 30, 34.8837209302326 | 29, 34.5238095238095 | 18, 21.4285714285714 | 77, 30.3149606299213 | NA |
Sex | |||||||
cat | |||||||
n | 2 | 1 | 86 | 84 | 84 | 254 | 0.140859828596478 |
Male | 2 | 2 | 33, 38.3720930232558 | 34, 40.4761904761905 | 44, 52.3809523809524 | 111, 43.7007874015748 | NA |
Female | 2 | 3 | 53, 61.6279069767442 | 50, 59.5238095238095 | 40, 47.6190476190476 | 143, 56.2992125984252 | NA |
Race (Origin) | |||||||
cat | |||||||
n | 3 | 1 | 86 | 84 | 84 | 254 | 0.647674941661787 |
Caucasian | 3 | 2 | 75, 87.2093023255814 | 72, 85.7142857142857 | 71, 84.5238095238095 | 218, 85.8267716535433 | NA |
African Descent | 3 | 3 | 8, 9.30232558139535 | 6, 7.14285714285714 | 9, 10.7142857142857 | 23, 9.05511811023622 | NA |
Hispanic | 3 | 4 | 3, 3.48837209302326 | 6, 7.14285714285714 | 3, 3.57142857142857 | 12, 4.7244094488189 | NA |
Other | 3 | 5 | NA, NA | NA, NA | 1, 1.19047619047619 | 1, 0.393700787401575 | NA |
MMSE | |||||||
cont | |||||||
n | 4 | 1 | 86 | 84 | 84 | 254 | 0.59465975941027 |
Mean | 4 | 2 | 18.046511627907 | 17.8690476190476 | 18.5119047619048 | 18.1417322834646 | NA |
SD | 4 | 3 | 4.2727783404855 | 4.22208696726523 | 4.15800591577738 | 4.21032874412179 | NA |
Median | 4 | 4 | 19.5 | 18 | 20 | 19 | NA |
Min | 4 | 5 | 10 | 10 | 10 | 10 | NA |
Max | 4 | 6 | 23 | 24 | 24 | 24 | NA |
Duration of disease | |||||||
cont | |||||||
n | 5 | 1 | 86 | 84 | 84 | 254 | 0.152960564175341 |
Mean | 5 | 2 | 42.65 | 48.6916666666667 | 40.5071428571429 | 43.9393700787402 | NA |
SD | 5 | 3 | 30.241571504451 | 29.5841711516636 | 24.6935472070355 | 28.3973156262964 | NA |
Median | 5 | 4 | 35.3 | 40.25 | 35.95 | 36.25 | NA |
Min | 5 | 5 | 7.2 | 7.8 | 2.2 | 2.2 | NA |
Max | 5 | 6 | 183.1 | 130.8 | 135 | 183.1 | NA |
cat | |||||||
<12 months | 5 | 7 | 5, 5.81395348837209 | 3, 3.57142857142857 | 4, 4.76190476190476 | 12, 4.7244094488189 | 0.788536928535063 |
>=12 months | 5 | 8 | 81, 94.1860465116279 | 81, 96.4285714285714 | 80, 95.2380952380952 | 242, 95.2755905511811 | NA |
Years of education | |||||||
cont | |||||||
n | 6 | 1 | 86 | 84 | 84 | 254 | 0.38750874992316 |
Mean | 6 | 2 | 12.5813953488372 | 13.1666666666667 | 12.5119047619048 | 12.751968503937 | NA |
SD | 6 | 3 | 2.94843973206596 | 4.14738510544312 | 2.91854910157261 | 3.3829227112292 | NA |
Median | 6 | 4 | 12 | 12 | 12 | 12 | NA |
Min | 6 | 5 | 6 | 3 | 6 | 3 | NA |
Max | 6 | 6 | 21 | 24 | 20 | 24 | NA |
Baseline weight(kg) | |||||||
cont | |||||||
n | 7 | 1 | 86 | 83 | 84 | 253 | 0.00304006274608553 |
Mean | 7 | 2 | 62.7593023255814 | 67.2795180722892 | 70.0047619047619 | 66.6478260869565 | NA |
SD | 7 | 3 | 12.7715435329253 | 14.1235986486909 | 14.6534333717795 | 14.1314255372792 | NA |
Median | 7 | 4 | 60.55 | 64.9 | 69.2 | 66.7 | NA |
Min | 7 | 5 | 34 | 45.4 | 41.7 | 34 | NA |
Max | 7 | 6 | 86.2 | 106.1 | 108 | 108 | NA |
Baseline height(cm) | |||||||
cont | |||||||
n | 8 | 1 | 86 | 84 | 84 | 254 | 0.126217916960126 |
Mean | 8 | 2 | 162.573255813953 | 163.433333333333 | 165.820238095238 | 163.931496062992 | NA |
SD | 8 | 3 | 11.5223611185188 | 10.4192400034262 | 10.1313515524819 | 10.7604472686284 | NA |
Median | 8 | 4 | 162.6 | 162.6 | 165.1 | 162.85 | NA |
Min | 8 | 5 | 137.2 | 135.9 | 146.1 | 135.9 | NA |
Max | 8 | 6 | 185.4 | 195.6 | 190.5 | 195.6 | NA |
Baseline BMI | |||||||
cont | |||||||
n | 9 | 1 | 86 | 83 | 84 | 253 | 0.0133190726378392 |
Mean | 9 | 2 | 23.6360465116279 | 25.0626506024096 | 25.347619047619 | 24.6723320158103 | NA |
SD | 9 | 3 | 3.67192569419556 | 4.27050893303881 | 4.15826876019846 | 4.09218492698334 | NA |
Median | 9 | 4 | 23.4 | 24.3 | 24.8 | 24.2 | NA |
Min | 9 | 5 | 15.1 | 17.7 | 13.7 | 13.7 | NA |
Max | 9 | 6 | 33.3 | 40.1 | 34.5 | 40.1 | NA |
cat | |||||||
<25 | 9 | 7 | 59, 68.6046511627907 | 47, 55.9523809523809 | 44, 52.3809523809524 | 150, 59.0551181102362 | 0.232621461976889 |
25-<30 | 9 | 8 | 21, 24.4186046511628 | 27, 32.1428571428571 | 28, 33.3333333333333 | 76, 29.9212598425197 | NA |
>=30 | 9 | 9 | 6, 6.97674418604651 | 10, 11.9047619047619 | 12, 14.2857142857143 | 28, 11.0236220472441 | NA |
While this makes a table, it isn’t a very nice table and definitely
doesn’t match the mock. So let’s start with formatting all the numbers.
To do this we are going to build a body_plan
to add to our
tfrmt
. This will be a fairly quick explanation of
body_plan
s but if you would like more information see
vignettes("Body Plan")
Body plans are made up of a series of frmt_stucture
s
where each frmt_stucture
represents the formatting of a
cell within the table. The order of the frmt_structure
s
matter; they are always applied latest to oldest. This means the first
frmt_stucture
in the body_plan
should be the
most generic. You can use the groups, labels and parameters to specify
which formatting applies to which values.
To start, we are going to use all the rows that are “n (%)” as the
default. This way we don’t need to list out every row that is an “n (%)”
row. These rows are made up of two different values, so we will need to
use frmt_combine
. Next, we can format the continuous
variables, which is just a straightforward one value per row so we can
just use the label to filter and frmt
to define the look.
Finally, we want to format the p-values. This is a bit more complicated,
since the p-value sits in the same row as other parameters; therefore
the group and label value are not specific enough and we need something
more granular. As such, we will need to specify the parameter in the
frmt_structure
like so:
frmt_structure(group_val = ".default", label_val = ".default", p = frmt("x.xx")
.
Further, we also need to make sure it never displays a rounded p-value
of 0 or 1. So we can use frmt_when
to specify the
formatting based on the value.
tfrmt(
# specify columns in the data
group = c(rowlbl1,grp),
label = rowlbl2,
column = column,
param = param,
value = value,
sorting_cols = c(ord1, ord2),
# specify value formatting
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = ".default", frmt_combine("{n} ({pct} %)",
n = frmt("xxx"),
pct = frmt("xx.x"))),
frmt_structure(group_val = ".default", label_val = "n", frmt("xxx")),
frmt_structure(group_val = ".default", label_val = c("Mean", "Median", "Min","Max"), frmt("xxx.x")),
frmt_structure(group_val = ".default", label_val = "SD", frmt("xxx.xx")),
frmt_structure(group_val = ".default", label_val = ".default", p = frmt_when(">0.99" ~ ">0.99",
"<0.001" ~ "<0.001",
TRUE ~ frmt("x.xxx", missing = "")))
)) %>%
print_to_gt(data_demog) %>%
tab_options(
container.width = 900
)
ord1 | ord2 | Placebo | Xanomeline Low Dose | Xanomeline High Dose | Total | p-value | |
---|---|---|---|---|---|---|---|
Age (y) | |||||||
cont | |||||||
n | 1 | 1 | 86 | 84 | 84 | 254 | 0.593 |
Mean | 1 | 2 | 75.2 | 75.7 | 74.4 | 75.1 | |
SD | 1 | 3 | 8.59 | 8.29 | 7.89 | 8.25 | |
Median | 1 | 4 | 76.0 | 77.5 | 76.0 | 77.0 | |
Min | 1 | 5 | 52.0 | 51.0 | 56.0 | 51.0 | |
Max | 1 | 6 | 89.0 | 88.0 | 88.0 | 89.0 | |
cat | |||||||
<65 yrs | 1 | 7 | 14 (16.3 %) | 8 ( 9.5 %) | 11 (13.1 %) | 33 (13.0 %) | 0.144 |
65-80 yrs | 1 | 8 | 42 (48.8 %) | 47 (56.0 %) | 55 (65.5 %) | 144 (56.7 %) | |
>80 yrs | 1 | 9 | 30 (34.9 %) | 29 (34.5 %) | 18 (21.4 %) | 77 (30.3 %) | |
Sex | |||||||
cat | |||||||
n | 2 | 1 | 86 | 84 | 84 | 254 | 0.141 |
Male | 2 | 2 | 33 (38.4 %) | 34 (40.5 %) | 44 (52.4 %) | 111 (43.7 %) | |
Female | 2 | 3 | 53 (61.6 %) | 50 (59.5 %) | 40 (47.6 %) | 143 (56.3 %) | |
Race (Origin) | |||||||
cat | |||||||
n | 3 | 1 | 86 | 84 | 84 | 254 | 0.648 |
Caucasian | 3 | 2 | 75 (87.2 %) | 72 (85.7 %) | 71 (84.5 %) | 218 (85.8 %) | |
African Descent | 3 | 3 | 8 ( 9.3 %) | 6 ( 7.1 %) | 9 (10.7 %) | 23 ( 9.1 %) | |
Hispanic | 3 | 4 | 3 ( 3.5 %) | 6 ( 7.1 %) | 3 ( 3.6 %) | 12 ( 4.7 %) | |
Other | 3 | 5 | 1 ( 1.2 %) | 1 ( 0.4 %) | |||
MMSE | |||||||
cont | |||||||
n | 4 | 1 | 86 | 84 | 84 | 254 | 0.595 |
Mean | 4 | 2 | 18.0 | 17.9 | 18.5 | 18.1 | |
SD | 4 | 3 | 4.27 | 4.22 | 4.16 | 4.21 | |
Median | 4 | 4 | 19.5 | 18.0 | 20.0 | 19.0 | |
Min | 4 | 5 | 10.0 | 10.0 | 10.0 | 10.0 | |
Max | 4 | 6 | 23.0 | 24.0 | 24.0 | 24.0 | |
Duration of disease | |||||||
cont | |||||||
n | 5 | 1 | 86 | 84 | 84 | 254 | 0.153 |
Mean | 5 | 2 | 42.6 | 48.7 | 40.5 | 43.9 | |
SD | 5 | 3 | 30.24 | 29.58 | 24.69 | 28.40 | |
Median | 5 | 4 | 35.3 | 40.2 | 36.0 | 36.2 | |
Min | 5 | 5 | 7.2 | 7.8 | 2.2 | 2.2 | |
Max | 5 | 6 | 183.1 | 130.8 | 135.0 | 183.1 | |
cat | |||||||
<12 months | 5 | 7 | 5 ( 5.8 %) | 3 ( 3.6 %) | 4 ( 4.8 %) | 12 ( 4.7 %) | 0.789 |
>=12 months | 5 | 8 | 81 (94.2 %) | 81 (96.4 %) | 80 (95.2 %) | 242 (95.3 %) | |
Years of education | |||||||
cont | |||||||
n | 6 | 1 | 86 | 84 | 84 | 254 | 0.388 |
Mean | 6 | 2 | 12.6 | 13.2 | 12.5 | 12.8 | |
SD | 6 | 3 | 2.95 | 4.15 | 2.92 | 3.38 | |
Median | 6 | 4 | 12.0 | 12.0 | 12.0 | 12.0 | |
Min | 6 | 5 | 6.0 | 3.0 | 6.0 | 3.0 | |
Max | 6 | 6 | 21.0 | 24.0 | 20.0 | 24.0 | |
Baseline weight(kg) | |||||||
cont | |||||||
n | 7 | 1 | 86 | 83 | 84 | 253 | 0.003 |
Mean | 7 | 2 | 62.8 | 67.3 | 70.0 | 66.6 | |
SD | 7 | 3 | 12.77 | 14.12 | 14.65 | 14.13 | |
Median | 7 | 4 | 60.5 | 64.9 | 69.2 | 66.7 | |
Min | 7 | 5 | 34.0 | 45.4 | 41.7 | 34.0 | |
Max | 7 | 6 | 86.2 | 106.1 | 108.0 | 108.0 | |
Baseline height(cm) | |||||||
cont | |||||||
n | 8 | 1 | 86 | 84 | 84 | 254 | 0.126 |
Mean | 8 | 2 | 162.6 | 163.4 | 165.8 | 163.9 | |
SD | 8 | 3 | 11.52 | 10.42 | 10.13 | 10.76 | |
Median | 8 | 4 | 162.6 | 162.6 | 165.1 | 162.8 | |
Min | 8 | 5 | 137.2 | 135.9 | 146.1 | 135.9 | |
Max | 8 | 6 | 185.4 | 195.6 | 190.5 | 195.6 | |
Baseline BMI | |||||||
cont | |||||||
n | 9 | 1 | 86 | 83 | 84 | 253 | 0.013 |
Mean | 9 | 2 | 23.6 | 25.1 | 25.3 | 24.7 | |
SD | 9 | 3 | 3.67 | 4.27 | 4.16 | 4.09 | |
Median | 9 | 4 | 23.4 | 24.3 | 24.8 | 24.2 | |
Min | 9 | 5 | 15.1 | 17.7 | 13.7 | 13.7 | |
Max | 9 | 6 | 33.3 | 40.1 | 34.5 | 40.1 | |
cat | |||||||
<25 | 9 | 7 | 59 (68.6 %) | 47 (56.0 %) | 44 (52.4 %) | 150 (59.1 %) | 0.233 |
25-<30 | 9 | 8 | 21 (24.4 %) | 27 (32.1 %) | 28 (33.3 %) | 76 (29.9 %) | |
>=30 | 9 | 9 | 6 ( 7.0 %) | 10 (11.9 %) | 12 (14.3 %) | 28 (11.0 %) |
Now that all the numbers look correct, we can drop the order columns
and the grp
column (note that while we do not want to
display the grp
column, it plays a role behind the scenes,
which will be addressed in the next step). To do this we use a
col_plan
which uses tidy-select
nomenclature
to drop/move columns.
tfrmt(
# specify columns in the data
group = c(rowlbl1,grp),
label = rowlbl2,
column = column,
param = param,
value = value,
sorting_cols = c(ord1, ord2),
# specify value formatting
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = ".default", frmt_combine("{n} {pct}",
n = frmt("xxx"),
pct = frmt_when("==100" ~ "",
"==0" ~ "",
TRUE ~ frmt("(xx.x %)")))),
frmt_structure(group_val = ".default", label_val = "n", frmt("xxx")),
frmt_structure(group_val = ".default", label_val = c("Mean", "Median", "Min","Max"), frmt("xxx.x")),
frmt_structure(group_val = ".default", label_val = "SD", frmt("xxx.xx")),
frmt_structure(group_val = ".default", label_val = ".default", p = frmt("")),
frmt_structure(group_val = ".default", label_val = c("n","<65 yrs","<12 months","<25"), p = frmt_when(">0.99" ~ ">0.99",
"<0.001" ~ "<0.001",
TRUE ~ frmt("x.xxx", missing = "")))
),
# remove extra cols
col_plan = col_plan(-grp,
-starts_with("ord") )) %>%
print_to_gt(data_demog) %>%
tab_options(
container.width = 900
)
Placebo | Xanomeline Low Dose | Xanomeline High Dose | Total | p-value | |
---|---|---|---|---|---|
Age (y) | |||||
n | 86 | 84 | 84 | 254 | 0.593 |
Mean | 75.2 | 75.7 | 74.4 | 75.1 | |
SD | 8.59 | 8.29 | 7.89 | 8.25 | |
Median | 76.0 | 77.5 | 76.0 | 77.0 | |
Min | 52.0 | 51.0 | 56.0 | 51.0 | |
Max | 89.0 | 88.0 | 88.0 | 89.0 | |
<65 yrs | 14 (16.3 %) | 8 ( 9.5 %) | 11 (13.1 %) | 33 (13.0 %) | 0.144 |
65-80 yrs | 42 (48.8 %) | 47 (56.0 %) | 55 (65.5 %) | 144 (56.7 %) | |
>80 yrs | 30 (34.9 %) | 29 (34.5 %) | 18 (21.4 %) | 77 (30.3 %) | |
Sex | |||||
n | 86 | 84 | 84 | 254 | 0.141 |
Male | 33 (38.4 %) | 34 (40.5 %) | 44 (52.4 %) | 111 (43.7 %) | |
Female | 53 (61.6 %) | 50 (59.5 %) | 40 (47.6 %) | 143 (56.3 %) | |
Race (Origin) | |||||
n | 86 | 84 | 84 | 254 | 0.648 |
Caucasian | 75 (87.2 %) | 72 (85.7 %) | 71 (84.5 %) | 218 (85.8 %) | |
African Descent | 8 ( 9.3 %) | 6 ( 7.1 %) | 9 (10.7 %) | 23 ( 9.1 %) | |
Hispanic | 3 ( 3.5 %) | 6 ( 7.1 %) | 3 ( 3.6 %) | 12 ( 4.7 %) | |
Other | 1 ( 1.2 %) | 1 ( 0.4 %) | |||
MMSE | |||||
n | 86 | 84 | 84 | 254 | 0.595 |
Mean | 18.0 | 17.9 | 18.5 | 18.1 | |
SD | 4.27 | 4.22 | 4.16 | 4.21 | |
Median | 19.5 | 18.0 | 20.0 | 19.0 | |
Min | 10.0 | 10.0 | 10.0 | 10.0 | |
Max | 23.0 | 24.0 | 24.0 | 24.0 | |
Duration of disease | |||||
n | 86 | 84 | 84 | 254 | 0.153 |
Mean | 42.6 | 48.7 | 40.5 | 43.9 | |
SD | 30.24 | 29.58 | 24.69 | 28.40 | |
Median | 35.3 | 40.2 | 36.0 | 36.2 | |
Min | 7.2 | 7.8 | 2.2 | 2.2 | |
Max | 183.1 | 130.8 | 135.0 | 183.1 | |
<12 months | 5 ( 5.8 %) | 3 ( 3.6 %) | 4 ( 4.8 %) | 12 ( 4.7 %) | 0.789 |
>=12 months | 81 (94.2 %) | 81 (96.4 %) | 80 (95.2 %) | 242 (95.3 %) | |
Years of education | |||||
n | 86 | 84 | 84 | 254 | 0.388 |
Mean | 12.6 | 13.2 | 12.5 | 12.8 | |
SD | 2.95 | 4.15 | 2.92 | 3.38 | |
Median | 12.0 | 12.0 | 12.0 | 12.0 | |
Min | 6.0 | 3.0 | 6.0 | 3.0 | |
Max | 21.0 | 24.0 | 20.0 | 24.0 | |
Baseline weight(kg) | |||||
n | 86 | 83 | 84 | 253 | 0.003 |
Mean | 62.8 | 67.3 | 70.0 | 66.6 | |
SD | 12.77 | 14.12 | 14.65 | 14.13 | |
Median | 60.5 | 64.9 | 69.2 | 66.7 | |
Min | 34.0 | 45.4 | 41.7 | 34.0 | |
Max | 86.2 | 106.1 | 108.0 | 108.0 | |
Baseline height(cm) | |||||
n | 86 | 84 | 84 | 254 | 0.126 |
Mean | 162.6 | 163.4 | 165.8 | 163.9 | |
SD | 11.52 | 10.42 | 10.13 | 10.76 | |
Median | 162.6 | 162.6 | 165.1 | 162.8 | |
Min | 137.2 | 135.9 | 146.1 | 135.9 | |
Max | 185.4 | 195.6 | 190.5 | 195.6 | |
Baseline BMI | |||||
n | 86 | 83 | 84 | 253 | 0.013 |
Mean | 23.6 | 25.1 | 25.3 | 24.7 | |
SD | 3.67 | 4.27 | 4.16 | 4.09 | |
Median | 23.4 | 24.3 | 24.8 | 24.2 | |
Min | 15.1 | 17.7 | 13.7 | 13.7 | |
Max | 33.3 | 40.1 | 34.5 | 40.1 | |
<25 | 59 (68.6 %) | 47 (56.0 %) | 44 (52.4 %) | 150 (59.1 %) | 0.233 |
25-<30 | 21 (24.4 %) | 27 (32.1 %) | 28 (33.3 %) | 76 (29.9 %) | |
>=30 | 6 ( 7.0 %) | 10 (11.9 %) | 12 (14.3 %) | 28 (11.0 %) |
Now this table looks just about right. There are two problems, (1)
alignment and (2) spacing between the continuous and categorical values.
To take care of the alignment we are going to add a
col_style_plan
which accepts a series of
col_style_structure
s. This allows columns to be aligned
differently if needed. For this table, we want all the columns to align
on either “.”, “,” or ” ” so our col_style_structure
looks
like
col_style_structure(align = c(".",","," "), col = vars(everything()))
.
After the alignment is sorted we can move on to the spacing. In order to
match the spacing of the mock we need to use the extra grp
column from our data. If we look at our data, we can see we want a space
any time either of the groups change.
data_demog %>%
distinct(rowlbl1,grp)
#> # A tibble: 12 × 2
#> # Groups: rowlbl1 [9]
#> rowlbl1 grp
#> <chr> <chr>
#> 1 "Age (y)" cont
#> 2 "Age (y)" cat
#> 3 "Sex" cat
#> 4 "Race (Origin)" cat
#> 5 "MMSE" cont
#> 6 "Duration of disease " cont
#> 7 "Duration of disease " cat
#> 8 "Years of education" cont
#> 9 "Baseline weight(kg)" cont
#> 10 "Baseline height(cm)" cont
#> 11 "Baseline BMI" cont
#> 12 "Baseline BMI" cat
This means that we can use a row_grp_plan
with just a
".default"
as the group value and it should handle all of
the spacing. In addition to the spacing, row_grp_plan
will
let us move the spanning group labels to a separate column by changing
the label_loc
to “column”.
tfrmt(
# specify columns in the data
group = c(rowlbl1,grp),
label = rowlbl2,
column = column,
param = param,
value = value,
sorting_cols = c(ord1, ord2),
# specify value formatting
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = ".default", frmt_combine("{n} {pct}",
n = frmt("xxx"),
pct = frmt_when("==100" ~ "",
"==0" ~ "",
TRUE ~ frmt("(xx.x %)")))),
frmt_structure(group_val = ".default", label_val = "n", frmt("xxx")),
frmt_structure(group_val = ".default", label_val = c("Mean", "Median", "Min","Max"), frmt("xxx.x")),
frmt_structure(group_val = ".default", label_val = "SD", frmt("xxx.xx")),
frmt_structure(group_val = ".default", label_val = ".default", p = frmt("")),
frmt_structure(group_val = ".default", label_val = c("n","<65 yrs","<12 months","<25"), p = frmt_when(">0.99" ~ ">0.99",
"<0.001" ~ "<0.001",
TRUE ~ frmt("x.xxx", missing = "")))
),
# remove extra cols
col_plan = col_plan(-grp,
-starts_with("ord") ),
# Specify column styling plan
col_style_plan = col_style_plan(
col_style_structure(align = c(".",","," "), col = c("Placebo", "Xanomeline Low Dose",
"Xanomeline High Dose", "Total", "p-value")),
col_style_structure(align = "left", col = c("rowlbl1","rowlbl2"))
),
# Specify row group plan
row_grp_plan = row_grp_plan(
row_grp_structure(group_val = ".default", element_block(post_space = " ")),
label_loc = element_row_grp_loc(location = "column")
)
) %>%
print_to_gt(data_demog) %>%
tab_options(
container.width = 900
)
Placebo | Xanomeline Low Dose | Xanomeline High Dose | Total | p-value | ||
---|---|---|---|---|---|---|
Age (y) | n | 86 | 84 | 84 | 254 | 0.593 |
Mean | 75.2 | 75.7 | 74.4 | 75.1 | ||
SD | 8.59 | 8.29 | 7.89 | 8.25 | ||
Median | 76.0 | 77.5 | 76.0 | 77.0 | ||
Min | 52.0 | 51.0 | 56.0 | 51.0 | ||
Max | 89.0 | 88.0 | 88.0 | 89.0 | ||
<65 yrs | 14 (16.3 %) | 8 ( 9.5 %) | 11 (13.1 %) | 33 (13.0 %) | 0.144 | |
65-80 yrs | 42 (48.8 %) | 47 (56.0 %) | 55 (65.5 %) | 144 (56.7 %) | ||
>80 yrs | 30 (34.9 %) | 29 (34.5 %) | 18 (21.4 %) | 77 (30.3 %) | ||
Sex | n | 86 | 84 | 84 | 254 | 0.141 |
Male | 33 (38.4 %) | 34 (40.5 %) | 44 (52.4 %) | 111 (43.7 %) | ||
Female | 53 (61.6 %) | 50 (59.5 %) | 40 (47.6 %) | 143 (56.3 %) | ||
Race (Origin) | n | 86 | 84 | 84 | 254 | 0.648 |
Caucasian | 75 (87.2 %) | 72 (85.7 %) | 71 (84.5 %) | 218 (85.8 %) | ||
African Descent | 8 ( 9.3 %) | 6 ( 7.1 %) | 9 (10.7 %) | 23 ( 9.1 %) | ||
Hispanic | 3 ( 3.5 %) | 6 ( 7.1 %) | 3 ( 3.6 %) | 12 ( 4.7 %) | ||
Other | 1 ( 1.2 %) | 1 ( 0.4 %) | ||||
MMSE | n | 86 | 84 | 84 | 254 | 0.595 |
Mean | 18.0 | 17.9 | 18.5 | 18.1 | ||
SD | 4.27 | 4.22 | 4.16 | 4.21 | ||
Median | 19.5 | 18.0 | 20.0 | 19.0 | ||
Min | 10.0 | 10.0 | 10.0 | 10.0 | ||
Max | 23.0 | 24.0 | 24.0 | 24.0 | ||
Duration of disease | n | 86 | 84 | 84 | 254 | 0.153 |
Mean | 42.6 | 48.7 | 40.5 | 43.9 | ||
SD | 30.24 | 29.58 | 24.69 | 28.40 | ||
Median | 35.3 | 40.2 | 36.0 | 36.2 | ||
Min | 7.2 | 7.8 | 2.2 | 2.2 | ||
Max | 183.1 | 130.8 | 135.0 | 183.1 | ||
<12 months | 5 ( 5.8 %) | 3 ( 3.6 %) | 4 ( 4.8 %) | 12 ( 4.7 %) | 0.789 | |
>=12 months | 81 (94.2 %) | 81 (96.4 %) | 80 (95.2 %) | 242 (95.3 %) | ||
Years of education | n | 86 | 84 | 84 | 254 | 0.388 |
Mean | 12.6 | 13.2 | 12.5 | 12.8 | ||
SD | 2.95 | 4.15 | 2.92 | 3.38 | ||
Median | 12.0 | 12.0 | 12.0 | 12.0 | ||
Min | 6.0 | 3.0 | 6.0 | 3.0 | ||
Max | 21.0 | 24.0 | 20.0 | 24.0 | ||
Baseline weight(kg) | n | 86 | 83 | 84 | 253 | 0.003 |
Mean | 62.8 | 67.3 | 70.0 | 66.6 | ||
SD | 12.77 | 14.12 | 14.65 | 14.13 | ||
Median | 60.5 | 64.9 | 69.2 | 66.7 | ||
Min | 34.0 | 45.4 | 41.7 | 34.0 | ||
Max | 86.2 | 106.1 | 108.0 | 108.0 | ||
Baseline height(cm) | n | 86 | 84 | 84 | 254 | 0.126 |
Mean | 162.6 | 163.4 | 165.8 | 163.9 | ||
SD | 11.52 | 10.42 | 10.13 | 10.76 | ||
Median | 162.6 | 162.6 | 165.1 | 162.8 | ||
Min | 137.2 | 135.9 | 146.1 | 135.9 | ||
Max | 185.4 | 195.6 | 190.5 | 195.6 | ||
Baseline BMI | n | 86 | 83 | 84 | 253 | 0.013 |
Mean | 23.6 | 25.1 | 25.3 | 24.7 | ||
SD | 3.67 | 4.27 | 4.16 | 4.09 | ||
Median | 23.4 | 24.3 | 24.8 | 24.2 | ||
Min | 15.1 | 17.7 | 13.7 | 13.7 | ||
Max | 33.3 | 40.1 | 34.5 | 40.1 | ||
<25 | 59 (68.6 %) | 47 (56.0 %) | 44 (52.4 %) | 150 (59.1 %) | 0.233 | |
25-<30 | 21 (24.4 %) | 27 (32.1 %) | 28 (33.3 %) | 76 (29.9 %) | ||
>=30 | 6 ( 7.0 %) | 10 (11.9 %) | 12 (14.3 %) | 28 (11.0 %) | ||
AE table
For the adverse events (AE) table, we will use the
data_ae
analysis results data, which is also based on the
CDISC pilot data. This dataset has two different row label columns,
AEBODSYS
and AETERM
, for system organ class
and preferred term, respectively. There are also two order columns which
will be used to set the row order of the output. Because this table has
column spanners, we have two column variables, col2
and
col1
to define the hierarchy of columns. Finally, there is
a param column and a value column. For brevity, we will subset to AEs
with >10% prevalence in the High Dose group.
Expand for the code used to produce this subset
#> # A tibble: 6 × 8
#> AEBODSYS AETERM col2 col1 param value ord1 ord2
#> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 ANY BODY SYSTEM ANY BODY SYSTEM Placebo n_pct n 65 0 0
#> 2 ANY BODY SYSTEM ANY BODY SYSTEM Placebo n_pct pct 75.6 0 0
#> 3 ANY BODY SYSTEM ANY BODY SYSTEM Placebo AEs AEs 281 0 0
#> 4 ANY BODY SYSTEM ANY BODY SYSTEM Xanomeline Low … n_pct n 77 0 0
#> 5 ANY BODY SYSTEM ANY BODY SYSTEM Xanomeline Low … n_pct pct 91.7 0 0
#> 6 ANY BODY SYSTEM ANY BODY SYSTEM Xanomeline Low … AEs AEs 412 0 0
The mock we are going to match looks like this:
Placebo
|
Xanomeline Low Dose
|
Xanomeline High Dose
|
fisher_pval
|
|||||
---|---|---|---|---|---|---|---|---|
n_pct | AEs | n_pct | AEs | n_pct | AEs | p_low | p_high | |
ANY BODY SYSTEM | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
CARDIAC DISORDERS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
GASTROINTESTINAL DISORDERS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
APPLICATION SITE PRURITUS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
APPLICATION SITE ERYTHEMA | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
APPLICATION SITE IRRITATION | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
INFECTIONS AND INFESTATIONS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
NERVOUS SYSTEM DISORDERS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
DIZZINESS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
SKIN AND SUBCUTANEOUS TISSUE DISORDERS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
PRURITUS | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
ERYTHEMA | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
RASH | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | XXX (xx.x %) | [XXX] | x.xxx | x.xxx |
For this table we have three treatment group columns (Placebo, Low, and High Dose) which each have the following values reported: # of subjects with at least one AE (n), percent of subjects with at least one AE (pct), and # of AEs (AEs). We also have two p-value columns (Low Dose vs. Placebo, High Dose vs. Placebo).
Like the demography example, the first thing we are going to do when
building out the tfrmt
is specify all our columns. Note
that col2
contains our spanning labels and
col1
contains our lower level column headers:
tfrmt(
# specify columns in the data
group = AEBODSYS,
label = AETERM,
column = c(col2, col1),
param = param,
value = value,
sorting_cols = c(ord1, ord2)) %>%
print_to_gt(data_ae2) %>%
tab_options(
container.width = 1000
)
#> The following rows of the given dataset have no format applied to them 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165
#> Multiple param listed for the same group/label values.
#> The following frmt_structures may be missing from the body_plan
#> or the order may need to be changed:
#> - `frmt_structure(group_val = "ANY BODY SYSTEM", label_val = "ANY BODY SYSTEM", frmt_combine("{n}, {pct}",n = frmt("xx"), pct = frmt("xx")))`
#> - `frmt_structure(group_val = "CARDIAC DISORDERS", label_val = "CARDIAC DISORDERS", frmt_combine("{n}, {pct}",n = frmt("xx"), pct = frmt("xx")))`
#> - `frmt_structure(group_val = "GASTROINTESTINAL DISORDERS", label_val = "GASTROINTESTINAL DISORDERS", frmt_combine("{n}, {pct}",n = frmt("xx"), pct = frmt("xx")))`
#> - `frmt_structure(group_val = "GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS", label_val = c("APPLICATION SITE ERYTHEMA","APPLICATION SITE IRRITATION","APPLICATION SITE PRURITUS","GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS"), frmt_combine("{n}, {pct}",n = frmt("xx"), pct = frmt("xx")))`
#> - `frmt_structure(group_val = "INFECTIONS AND INFESTATIONS", label_val = "INFECTIONS AND INFESTATIONS", frmt_combine("{n}, {pct}",n = frmt("xx"), pct = frmt("xx")))`
#> - `frmt_structure(group_val = "NERVOUS SYSTEM DISORDERS", label_val = c("DIZZINESS","NERVOUS SYSTEM DISORDERS"), frmt_combine("{n}, {pct}",n = frmt("xx"), pct = frmt("xx")))`
#> - `frmt_structure(group_val = "RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS", label_val = c("RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS"), frmt_combine("{n}, {pct}",n = frmt("xx"), pct = frmt("xx")))`
#> - `frmt_structure(group_val = "SKIN AND SUBCUTANEOUS TISSUE DISORDERS", label_val = c("ERYTHEMA","PRURITUS","RASH","SKIN AND SUBCUTANEOUS TISSUE DISORDERS"), frmt_combine("{n}, {pct}",n = frmt("xx"), pct = frmt("xx")))`
ord1 | ord2 |
Placebo
|
Xanomeline Low Dose
|
Xanomeline High Dose
|
fisher_pval
|
|||||
---|---|---|---|---|---|---|---|---|---|---|
n_pct | AEs | n_pct | AEs | n_pct | AEs | p_low | p_high | |||
ANY BODY SYSTEM | 0 | 0 | 65, 75.5813953488372 | 281 | 77, 91.6666666666667 | 412 | 76, 90.4761904761905 | 433 | 0.00653312936477891 | 0.0136376915028284 |
CARDIAC DISORDERS | 1 | 0 | 12, 13.953488372093 | 26 | 13, 15.4761904761905 | 30 | 15, 17.8571428571429 | 30 | 0.830838674053784 | 0.533664723024524 |
GASTROINTESTINAL DISORDERS | 5 | 0 | 17, 19.7674418604651 | 26 | 14, 16.6666666666667 | 22 | 20, 23.8095238095238 | 36 | 0.692428919010868 | 0.579522945659183 |
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS | 6 | 0 | 21, 24.4186046511628 | 46 | 47, 55.9523809523809 | 118 | 40, 47.6190476190476 | 124 | 4.01936476971637e-05 | 0.00227387200885964 |
APPLICATION SITE PRURITUS | 6 | 1 | 6, 6.97674418604651 | 10 | 22, 26.1904761904762 | 32 | 22, 26.1904761904762 | 35 | 0.000811758368600543 | 0.000811758368600543 |
APPLICATION SITE ERYTHEMA | 6 | 1 | 3, 3.48837209302326 | 3 | 12, 14.2857142857143 | 20 | 15, 17.8571428571429 | 23 | 0.0151667414143154 | 0.00248031755239288 |
APPLICATION SITE IRRITATION | 6 | 1 | 3, 3.48837209302326 | 7 | 9, 10.7142857142857 | 18 | 9, 10.7142857142857 | 16 | 0.078319062603502 | 0.078319062603502 |
INFECTIONS AND INFESTATIONS | 9 | 0 | 16, 18.6046511627907 | 35 | 9, 10.7142857142857 | 16 | 13, 15.4761904761905 | 20 | 0.194038579805755 | 0.684680584558915 |
NERVOUS SYSTEM DISORDERS | 15 | 0 | 8, 9.30232558139535 | 11 | 20, 23.8095238095238 | 40 | 25, 29.7619047619048 | 41 | 0.0129835630195297 | 0.000870133171350475 |
DIZZINESS | 15 | 1 | 2, 2.32558139534884 | 3 | 8, 9.52380952380952 | 13 | 11, 13.0952380952381 | 15 | 0.0556186226520671 | 0.009253648876646 |
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS | 19 | 0 | 8, 9.30232558139535 | 12 | 9, 10.7142857142857 | 14 | 10, 11.9047619047619 | 22 | 0.802870189478092 | 0.625582203021787 |
SKIN AND SUBCUTANEOUS TISSUE DISORDERS | 20 | 0 | 20, 23.2558139534884 | 45 | 39, 46.4285714285714 | 111 | 40, 47.6190476190476 | 104 | 0.00210032738584151 | 0.0012509423867864 |
PRURITUS | 20 | 1 | 8, 9.30232558139535 | 11 | 21, 25 | 31 | 26, 30.952380952381 | 38 | 0.00784138633137627 | 0.000480743020332539 |
ERYTHEMA | 20 | 1 | 8, 9.30232558139535 | 12 | 14, 16.6666666666667 | 22 | 14, 16.6666666666667 | 22 | 0.175425360790723 | 0.175425360790723 |
RASH | 20 | 1 | 5, 5.81395348837209 | 9 | 13, 15.4761904761905 | 18 | 9, 10.7142857142857 | 15 | 0.048021070861557 | 0.276671966759128 |
Next, we need to format the values using the body_plan
.
Recall that our body plan will be made up of a series of
frmt_stucture
s where each frmt_stucture
represents the formatting of a cell within the table. Our AE table boils
down to the following values: # of subjects with at least one AE (n),
percent of subjects with at least one AE (pct), # of AEs (AEs), and
p-value (pval). Because our n and pct will be combined using
frmt_combine
, we will have 3 frmt_structure
objects. Note the use of frmt_when
to format the
p-values.
tfrmt(
# specify columns in the data
group = AEBODSYS,
label = AETERM,
column = c(col2, col1),
param = param,
value = value,
sorting_cols = c(ord1, ord2),
# specify value formatting
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = ".default",
frmt_combine("{n} {pct}",
n = frmt("XXX"),
pct = frmt_when(
"==100" ~ "",
"==0" ~ "",
TRUE ~ frmt("(xx.x %)")))),
frmt_structure(group_val = ".default", label_val = ".default",
AEs = frmt("[XXX]")),
frmt_structure(group_val = ".default", label_val = ".default",
pval = frmt_when(">0.99" ~ ">0.99",
"<0.001" ~ "<0.001",
"<0.05" ~ frmt("x.xxx*"),
TRUE ~ frmt("x.xxx", missing ="--")))
)) %>%
print_to_gt(., data_ae2) %>%
tab_options(
container.width = 1000
)
ord1 | ord2 |
Placebo
|
Xanomeline Low Dose
|
Xanomeline High Dose
|
fisher_pval
|
|||||
---|---|---|---|---|---|---|---|---|---|---|
n_pct | AEs | n_pct | AEs | n_pct | AEs | p_low | p_high | |||
ANY BODY SYSTEM | 0 | 0 | 65 (75.6 %) | [281] | 77 (91.7 %) | [412] | 76 (90.5 %) | [433] | 0.007* | 0.014* |
CARDIAC DISORDERS | 1 | 0 | 12 (14.0 %) | [ 26] | 13 (15.5 %) | [ 30] | 15 (17.9 %) | [ 30] | 0.831 | 0.534 |
GASTROINTESTINAL DISORDERS | 5 | 0 | 17 (19.8 %) | [ 26] | 14 (16.7 %) | [ 22] | 20 (23.8 %) | [ 36] | 0.692 | 0.580 |
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS | 6 | 0 | 21 (24.4 %) | [ 46] | 47 (56.0 %) | [118] | 40 (47.6 %) | [124] | <0.001 | 0.002* |
APPLICATION SITE PRURITUS | 6 | 1 | 6 ( 7.0 %) | [ 10] | 22 (26.2 %) | [ 32] | 22 (26.2 %) | [ 35] | <0.001 | <0.001 |
APPLICATION SITE ERYTHEMA | 6 | 1 | 3 ( 3.5 %) | [ 3] | 12 (14.3 %) | [ 20] | 15 (17.9 %) | [ 23] | 0.015* | 0.002* |
APPLICATION SITE IRRITATION | 6 | 1 | 3 ( 3.5 %) | [ 7] | 9 (10.7 %) | [ 18] | 9 (10.7 %) | [ 16] | 0.078 | 0.078 |
INFECTIONS AND INFESTATIONS | 9 | 0 | 16 (18.6 %) | [ 35] | 9 (10.7 %) | [ 16] | 13 (15.5 %) | [ 20] | 0.194 | 0.685 |
NERVOUS SYSTEM DISORDERS | 15 | 0 | 8 ( 9.3 %) | [ 11] | 20 (23.8 %) | [ 40] | 25 (29.8 %) | [ 41] | 0.013* | <0.001 |
DIZZINESS | 15 | 1 | 2 ( 2.3 %) | [ 3] | 8 ( 9.5 %) | [ 13] | 11 (13.1 %) | [ 15] | 0.056 | 0.009* |
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS | 19 | 0 | 8 ( 9.3 %) | [ 12] | 9 (10.7 %) | [ 14] | 10 (11.9 %) | [ 22] | 0.803 | 0.626 |
SKIN AND SUBCUTANEOUS TISSUE DISORDERS | 20 | 0 | 20 (23.3 %) | [ 45] | 39 (46.4 %) | [111] | 40 (47.6 %) | [104] | 0.002* | 0.001* |
PRURITUS | 20 | 1 | 8 ( 9.3 %) | [ 11] | 21 (25.0 %) | [ 31] | 26 (31.0 %) | [ 38] | 0.008* | <0.001 |
ERYTHEMA | 20 | 1 | 8 ( 9.3 %) | [ 12] | 14 (16.7 %) | [ 22] | 14 (16.7 %) | [ 22] | 0.175 | 0.175 |
RASH | 20 | 1 | 5 ( 5.8 %) | [ 9] | 13 (15.5 %) | [ 18] | 9 (10.7 %) | [ 15] | 0.048* | 0.277 |
Almost there! Our AE table contains data for both Preferred Terms and
System Organ Classes. Therefore, we do not want a typical group-level
header. Instead, we want to display the System Organ Class label inline
with its data, and nest the Preferred Term data underneath. Fortunately,
we are able to achieve this formatting with a
row_grp_plan
:
tfrmt(
# specify columns in the data
group = AEBODSYS,
label = AETERM,
column = c(col2, col1),
param = param,
value = value,
sorting_cols = c(ord1, ord2),
# specify value formatting
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = ".default",
frmt_combine("{n} {pct}",
n = frmt("XXX"),
pct = frmt_when(
"==100" ~ "",
"==0" ~ "",
TRUE ~ frmt("(xx.x %)")))),
frmt_structure(group_val = ".default", label_val = ".default",
AEs = frmt("[XXX]")),
frmt_structure(group_val = ".default", label_val = ".default",
pval = frmt_when(">0.99" ~ ">0.99",
"<0.001" ~ "<0.001",
"<0.05" ~ frmt("x.xxx*"),
TRUE ~ frmt("x.xxx", missing ="--")))
),
# Nest Preferred terms under SOC
row_grp_plan = row_grp_plan(label_loc = element_row_grp_loc(location = "indented"))
) %>%
print_to_gt(data_ae2) %>%
tab_options(
container.width = 1000
)
ord1 | ord2 |
Placebo
|
Xanomeline Low Dose
|
Xanomeline High Dose
|
fisher_pval
|
|||||
---|---|---|---|---|---|---|---|---|---|---|
n_pct | AEs | n_pct | AEs | n_pct | AEs | p_low | p_high | |||
ANY BODY SYSTEM | 0 | 0 | 65 (75.6 %) | [281] | 77 (91.7 %) | [412] | 76 (90.5 %) | [433] | 0.007* | 0.014* |
CARDIAC DISORDERS | 1 | 0 | 12 (14.0 %) | [ 26] | 13 (15.5 %) | [ 30] | 15 (17.9 %) | [ 30] | 0.831 | 0.534 |
GASTROINTESTINAL DISORDERS | 5 | 0 | 17 (19.8 %) | [ 26] | 14 (16.7 %) | [ 22] | 20 (23.8 %) | [ 36] | 0.692 | 0.580 |
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS | 6 | 0 | 21 (24.4 %) | [ 46] | 47 (56.0 %) | [118] | 40 (47.6 %) | [124] | <0.001 | 0.002* |
APPLICATION SITE PRURITUS | 6 | 1 | 6 ( 7.0 %) | [ 10] | 22 (26.2 %) | [ 32] | 22 (26.2 %) | [ 35] | <0.001 | <0.001 |
APPLICATION SITE ERYTHEMA | 6 | 1 | 3 ( 3.5 %) | [ 3] | 12 (14.3 %) | [ 20] | 15 (17.9 %) | [ 23] | 0.015* | 0.002* |
APPLICATION SITE IRRITATION | 6 | 1 | 3 ( 3.5 %) | [ 7] | 9 (10.7 %) | [ 18] | 9 (10.7 %) | [ 16] | 0.078 | 0.078 |
INFECTIONS AND INFESTATIONS | 9 | 0 | 16 (18.6 %) | [ 35] | 9 (10.7 %) | [ 16] | 13 (15.5 %) | [ 20] | 0.194 | 0.685 |
NERVOUS SYSTEM DISORDERS | 15 | 0 | 8 ( 9.3 %) | [ 11] | 20 (23.8 %) | [ 40] | 25 (29.8 %) | [ 41] | 0.013* | <0.001 |
DIZZINESS | 15 | 1 | 2 ( 2.3 %) | [ 3] | 8 ( 9.5 %) | [ 13] | 11 (13.1 %) | [ 15] | 0.056 | 0.009* |
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS | 19 | 0 | 8 ( 9.3 %) | [ 12] | 9 (10.7 %) | [ 14] | 10 (11.9 %) | [ 22] | 0.803 | 0.626 |
SKIN AND SUBCUTANEOUS TISSUE DISORDERS | 20 | 0 | 20 (23.3 %) | [ 45] | 39 (46.4 %) | [111] | 40 (47.6 %) | [104] | 0.002* | 0.001* |
PRURITUS | 20 | 1 | 8 ( 9.3 %) | [ 11] | 21 (25.0 %) | [ 31] | 26 (31.0 %) | [ 38] | 0.008* | <0.001 |
ERYTHEMA | 20 | 1 | 8 ( 9.3 %) | [ 12] | 14 (16.7 %) | [ 22] | 14 (16.7 %) | [ 22] | 0.175 | 0.175 |
RASH | 20 | 1 | 5 ( 5.8 %) | [ 9] | 13 (15.5 %) | [ 18] | 9 (10.7 %) | [ 15] | 0.048* | 0.277 |
Our column alignment looks good as-is, except for the p-values. We
can use the col_style_plan
to tweak those.
tfrmt(
# specify columns in the data
group = AEBODSYS,
label = AETERM,
column = c(col2, col1),
param = param,
value = value,
sorting_cols = c(ord1, ord2),
# specify value formatting
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = ".default",
frmt_combine("{n} {pct}",
n = frmt("XXX"),
pct = frmt_when(
"==100" ~ "",
"==0" ~ "",
TRUE ~ frmt("(xx.x %)")))),
frmt_structure(group_val = ".default", label_val = ".default",
AEs = frmt("[XXX]")),
frmt_structure(group_val = ".default", label_val = ".default",
pval = frmt_when(">0.99" ~ ">0.99",
"<0.001" ~ "<0.001",
"<0.05" ~ frmt("x.xxx*"),
TRUE ~ frmt("x.xxx", missing ="--")))
),
# Nest Preferred terms under SOC
row_grp_plan = row_grp_plan(label_loc = element_row_grp_loc(location = "indented")),
# alignment
# Specify column styling plan
col_style_plan = col_style_plan(
col_style_structure(align = c(".",","," "), col = vars(starts_with("p_")))
)
) %>%
print_to_gt(data_ae2) %>%
tab_options(
container.width = 1000
)
ord1 | ord2 |
Placebo
|
Xanomeline Low Dose
|
Xanomeline High Dose
|
fisher_pval
|
|||||
---|---|---|---|---|---|---|---|---|---|---|
n_pct | AEs | n_pct | AEs | n_pct | AEs | p_low | p_high | |||
ANY BODY SYSTEM | 0 | 0 | 65 (75.6 %) | [281] | 77 (91.7 %) | [412] | 76 (90.5 %) | [433] | 0.007* | 0.014* |
CARDIAC DISORDERS | 1 | 0 | 12 (14.0 %) | [ 26] | 13 (15.5 %) | [ 30] | 15 (17.9 %) | [ 30] | 0.831 | 0.534 |
GASTROINTESTINAL DISORDERS | 5 | 0 | 17 (19.8 %) | [ 26] | 14 (16.7 %) | [ 22] | 20 (23.8 %) | [ 36] | 0.692 | 0.580 |
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS | 6 | 0 | 21 (24.4 %) | [ 46] | 47 (56.0 %) | [118] | 40 (47.6 %) | [124] | <0.001 | 0.002* |
APPLICATION SITE PRURITUS | 6 | 1 | 6 ( 7.0 %) | [ 10] | 22 (26.2 %) | [ 32] | 22 (26.2 %) | [ 35] | <0.001 | <0.001 |
APPLICATION SITE ERYTHEMA | 6 | 1 | 3 ( 3.5 %) | [ 3] | 12 (14.3 %) | [ 20] | 15 (17.9 %) | [ 23] | 0.015* | 0.002* |
APPLICATION SITE IRRITATION | 6 | 1 | 3 ( 3.5 %) | [ 7] | 9 (10.7 %) | [ 18] | 9 (10.7 %) | [ 16] | 0.078 | 0.078 |
INFECTIONS AND INFESTATIONS | 9 | 0 | 16 (18.6 %) | [ 35] | 9 (10.7 %) | [ 16] | 13 (15.5 %) | [ 20] | 0.194 | 0.685 |
NERVOUS SYSTEM DISORDERS | 15 | 0 | 8 ( 9.3 %) | [ 11] | 20 (23.8 %) | [ 40] | 25 (29.8 %) | [ 41] | 0.013* | <0.001 |
DIZZINESS | 15 | 1 | 2 ( 2.3 %) | [ 3] | 8 ( 9.5 %) | [ 13] | 11 (13.1 %) | [ 15] | 0.056 | 0.009* |
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS | 19 | 0 | 8 ( 9.3 %) | [ 12] | 9 (10.7 %) | [ 14] | 10 (11.9 %) | [ 22] | 0.803 | 0.626 |
SKIN AND SUBCUTANEOUS TISSUE DISORDERS | 20 | 0 | 20 (23.3 %) | [ 45] | 39 (46.4 %) | [111] | 40 (47.6 %) | [104] | 0.002* | 0.001* |
PRURITUS | 20 | 1 | 8 ( 9.3 %) | [ 11] | 21 (25.0 %) | [ 31] | 26 (31.0 %) | [ 38] | 0.008* | <0.001 |
ERYTHEMA | 20 | 1 | 8 ( 9.3 %) | [ 12] | 14 (16.7 %) | [ 22] | 14 (16.7 %) | [ 22] | 0.175 | 0.175 |
RASH | 20 | 1 | 5 ( 5.8 %) | [ 9] | 13 (15.5 %) | [ 18] | 9 (10.7 %) | [ 15] | 0.048* | 0.277 |
Notice that we still have our order columns and the column labels
could benefit from some renaming. We can add a col_plan
to
help with the ordering:
tfrmt(
# specify columns in the data
group = AEBODSYS,
label = AETERM,
column = c(col2, col1),
param = param,
value = value,
sorting_cols = c(ord1, ord2),
# specify value formatting
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = ".default",
frmt_combine("{n} {pct}",
n = frmt("XXX"),
pct = frmt_when(
"==100" ~ "",
"==0" ~ "",
TRUE ~ frmt("(xx.x %)")))),
frmt_structure(group_val = ".default", label_val = ".default",
AEs = frmt("[XXX]")),
frmt_structure(group_val = ".default", label_val = ".default",
pval = frmt_when(">0.99" ~ ">0.99",
"<0.001" ~ "<0.001",
"<0.05" ~ frmt("x.xxx*"),
TRUE ~ frmt("x.xxx", missing ="--")))
),
# Nest Preferred terms under SOC
row_grp_plan = row_grp_plan(label_loc = element_row_grp_loc(location = "indented")),
# Specify column styling plan
col_style_plan = col_style_plan(
col_style_structure(align = c(".",","," "), col = vars(p_low, p_high))
),
# columns
col_plan = col_plan(
-starts_with("ord")
)
) %>%
print_to_gt(data_ae2) %>%
tab_options(
container.width = 1000
)
Placebo
|
Xanomeline Low Dose
|
Xanomeline High Dose
|
fisher_pval
|
|||||
---|---|---|---|---|---|---|---|---|
n_pct | AEs | n_pct | AEs | n_pct | AEs | p_low | p_high | |
ANY BODY SYSTEM | 65 (75.6 %) | [281] | 77 (91.7 %) | [412] | 76 (90.5 %) | [433] | 0.007* | 0.014* |
CARDIAC DISORDERS | 12 (14.0 %) | [ 26] | 13 (15.5 %) | [ 30] | 15 (17.9 %) | [ 30] | 0.831 | 0.534 |
GASTROINTESTINAL DISORDERS | 17 (19.8 %) | [ 26] | 14 (16.7 %) | [ 22] | 20 (23.8 %) | [ 36] | 0.692 | 0.580 |
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS | 21 (24.4 %) | [ 46] | 47 (56.0 %) | [118] | 40 (47.6 %) | [124] | <0.001 | 0.002* |
APPLICATION SITE PRURITUS | 6 ( 7.0 %) | [ 10] | 22 (26.2 %) | [ 32] | 22 (26.2 %) | [ 35] | <0.001 | <0.001 |
APPLICATION SITE ERYTHEMA | 3 ( 3.5 %) | [ 3] | 12 (14.3 %) | [ 20] | 15 (17.9 %) | [ 23] | 0.015* | 0.002* |
APPLICATION SITE IRRITATION | 3 ( 3.5 %) | [ 7] | 9 (10.7 %) | [ 18] | 9 (10.7 %) | [ 16] | 0.078 | 0.078 |
INFECTIONS AND INFESTATIONS | 16 (18.6 %) | [ 35] | 9 (10.7 %) | [ 16] | 13 (15.5 %) | [ 20] | 0.194 | 0.685 |
NERVOUS SYSTEM DISORDERS | 8 ( 9.3 %) | [ 11] | 20 (23.8 %) | [ 40] | 25 (29.8 %) | [ 41] | 0.013* | <0.001 |
DIZZINESS | 2 ( 2.3 %) | [ 3] | 8 ( 9.5 %) | [ 13] | 11 (13.1 %) | [ 15] | 0.056 | 0.009* |
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS | 8 ( 9.3 %) | [ 12] | 9 (10.7 %) | [ 14] | 10 (11.9 %) | [ 22] | 0.803 | 0.626 |
SKIN AND SUBCUTANEOUS TISSUE DISORDERS | 20 (23.3 %) | [ 45] | 39 (46.4 %) | [111] | 40 (47.6 %) | [104] | 0.002* | 0.001* |
PRURITUS | 8 ( 9.3 %) | [ 11] | 21 (25.0 %) | [ 31] | 26 (31.0 %) | [ 38] | 0.008* | <0.001 |
ERYTHEMA | 8 ( 9.3 %) | [ 12] | 14 (16.7 %) | [ 22] | 14 (16.7 %) | [ 22] | 0.175 | 0.175 |
RASH | 5 ( 5.8 %) | [ 9] | 13 (15.5 %) | [ 18] | 9 (10.7 %) | [ 15] | 0.048* | 0.277 |
For better control over our column labels, we can make use of
col_plan
’s span_structure
s to define the
column labels and spanners order and names:
tfrmt(
# specify columns in the data
group = AEBODSYS,
label = AETERM,
column = c(col2, col1),
param = param,
value = value,
sorting_cols = c(ord1, ord2),
# specify value formatting
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = ".default",
frmt_combine("{n} {pct}",
n = frmt("XXX"),
pct = frmt_when(
"==100" ~ "",
"==0" ~ "",
TRUE ~ frmt("(xx.x %)")))),
frmt_structure(group_val = ".default", label_val = ".default",
AEs = frmt("[XXX]")),
frmt_structure(group_val = ".default", label_val = ".default",
pval = frmt_when(">0.99" ~ ">0.99",
"<0.001" ~ "<0.001",
"<0.05" ~ frmt("x.xxx*"),
TRUE ~ frmt("x.xxx", missing ="--")))
),
# Nest Preferred terms under SOC
row_grp_plan = row_grp_plan(label_loc = element_row_grp_loc(location = "indented")),
# Specify column styling plan
col_style_plan = col_style_plan(
col_style_structure(align = c(".",","," "), col = c(p_low, p_high))
),
# columns
col_plan = col_plan(
## defines the spanning column order, and then beneath them the order of their contents
-starts_with("ord"),
span_structure(
col2 = c(
"Xanomeline High Dose (N=84)" = `Xanomeline High Dose`,
"Xanomeline Low Dose (N=84)" = `Xanomeline Low Dose`,
"Placebo (N=86)" = Placebo
),
col1 = c(`n (%)` = `n_pct` ,
`[AEs]` = `AEs`)
),
span_structure(
col2 = c("Fisher's Exact p-values" = fisher_pval),
col1 = c(
# add a line break to help with table formatting
`Placebo vs.\n Low Dose` = `p_low` ,
`Placebo vs.\n High Dose` = `p_high`
)
))
) %>%
print_to_gt(data_ae2) %>%
tab_options(
container.width = 1000
)
Placebo (N=86)
|
Xanomeline Low Dose (N=84)
|
Xanomeline High Dose (N=84)
|
Fisher’s Exact p-values
|
|||||
---|---|---|---|---|---|---|---|---|
n (%) | [AEs] | n (%) | [AEs] | n (%) | [AEs] | Placebo vs. Low Dose | Placebo vs. High Dose | |
ANY BODY SYSTEM | 65 (75.6 %) | [281] | 77 (91.7 %) | [412] | 76 (90.5 %) | [433] | 0.007* | 0.014* |
CARDIAC DISORDERS | 12 (14.0 %) | [ 26] | 13 (15.5 %) | [ 30] | 15 (17.9 %) | [ 30] | 0.831 | 0.534 |
GASTROINTESTINAL DISORDERS | 17 (19.8 %) | [ 26] | 14 (16.7 %) | [ 22] | 20 (23.8 %) | [ 36] | 0.692 | 0.580 |
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS | 21 (24.4 %) | [ 46] | 47 (56.0 %) | [118] | 40 (47.6 %) | [124] | <0.001 | 0.002* |
APPLICATION SITE PRURITUS | 6 ( 7.0 %) | [ 10] | 22 (26.2 %) | [ 32] | 22 (26.2 %) | [ 35] | <0.001 | <0.001 |
APPLICATION SITE ERYTHEMA | 3 ( 3.5 %) | [ 3] | 12 (14.3 %) | [ 20] | 15 (17.9 %) | [ 23] | 0.015* | 0.002* |
APPLICATION SITE IRRITATION | 3 ( 3.5 %) | [ 7] | 9 (10.7 %) | [ 18] | 9 (10.7 %) | [ 16] | 0.078 | 0.078 |
INFECTIONS AND INFESTATIONS | 16 (18.6 %) | [ 35] | 9 (10.7 %) | [ 16] | 13 (15.5 %) | [ 20] | 0.194 | 0.685 |
NERVOUS SYSTEM DISORDERS | 8 ( 9.3 %) | [ 11] | 20 (23.8 %) | [ 40] | 25 (29.8 %) | [ 41] | 0.013* | <0.001 |
DIZZINESS | 2 ( 2.3 %) | [ 3] | 8 ( 9.5 %) | [ 13] | 11 (13.1 %) | [ 15] | 0.056 | 0.009* |
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS | 8 ( 9.3 %) | [ 12] | 9 (10.7 %) | [ 14] | 10 (11.9 %) | [ 22] | 0.803 | 0.626 |
SKIN AND SUBCUTANEOUS TISSUE DISORDERS | 20 (23.3 %) | [ 45] | 39 (46.4 %) | [111] | 40 (47.6 %) | [104] | 0.002* | 0.001* |
PRURITUS | 8 ( 9.3 %) | [ 11] | 21 (25.0 %) | [ 31] | 26 (31.0 %) | [ 38] | 0.008* | <0.001 |
ERYTHEMA | 8 ( 9.3 %) | [ 12] | 14 (16.7 %) | [ 22] | 14 (16.7 %) | [ 22] | 0.175 | 0.175 |
RASH | 5 ( 5.8 %) | [ 9] | 13 (15.5 %) | [ 18] | 9 (10.7 %) | [ 15] | 0.048* | 0.277 |
Our AE table is now complete!
Efficacy
For this example, we will use the data_efficacy
dataset,
an example analysis results dataset found in the package, which is based
on the CDISC pilot data for the ADAS-Cog(11) score. The goal is to
recreate table 14-3.01 from the CDISC pilot.
This data is relatively simple in that it contains only 1
group
column and column
column, but it adds
complexity in that multiple analyses are stacked together - summary
statistics of different values at different time points, and the results
of several different ANCOVA models. Multiple treatment groups as well as
the contrasts between groups are included.
#> # A tibble: 6 × 7
#> group label column param value ord1 ord2
#> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 Baseline n Placebo n 79 1 1
#> 2 Baseline n Xanomeline Low Dose n 81 1 1
#> 3 Baseline n Xanomeline High Dose n 74 1 1
#> 4 Baseline Mean (SD) Placebo mean 24.1 1 2
#> 5 Baseline Mean (SD) Xanomeline Low Dose mean 24.4 1 2
#> 6 Baseline Mean (SD) Xanomeline High Dose mean 21.3 1 2
The mock we are going to match looks like this:
Placebo | Xanomeline Low Dose | Xanomeline High Dose | ord1 | ord2 | |
---|---|---|---|---|---|
Baseline | |||||
n | xx | xx | xx | 1 | 1 |
Mean (SD) | xx.x (xx.xx) | xx.x (xx.xx) | xx.x (xx.xx) | 1 | 2 |
Median (Range) | xx.x (xx;xx) | xx.x (xx;xx) | xx.x (xx;xx) | 1 | 3 |
Week 24 | |||||
n | xx | xx | xx | 2 | 1 |
Mean (SD) | xx.x (xx.xx) | xx.x (xx.xx) | xx.x (xx.xx) | 2 | 2 |
Median (Range) | xx.x (xx;xx) | xx.x (xx;xx) | xx.x (xx;xx) | 2 | 3 |
Change from Baseline | |||||
n | xx | xx | xx | 3 | 1 |
Mean (SD) | xx.x (xx.xx) | xx.x (xx.xx) | xx.x (xx.xx) | 3 | 2 |
Median (Range) | xx.x (xx;xx) | xx.x (xx;xx) | xx.x (xx;xx) | 3 | 3 |
3 | 3 | ||||
p-value (Dose Response) | x.xxx | 4 | 4 | ||
4 | 4 | ||||
p-value (Xan - Placebo) | x.xxx | x.xxx | 5 | 4 | |
Diff of LS Means (SE) | xx.x (xx.xx) | xx.x (xx.xx) | 5 | 5 | |
95% CI | (xx.x;xx.x) | (xx.x;xx.x) | 5 | 6 | |
5 | 6 | ||||
p-value (Xan High - Xan Low) | x.xxx | 6 | 4 | ||
Diff of LS Means (SE) | xx.x (xx.xx) | 6 | 5 | ||
95% CI | (xx.x;xx.x) | 6 | 6 |
Let’s first see how the table looks without any special formatting.
tfrmt(
group = group,
label = label,
column = column,
param = param,
value = value
) %>%
print_to_gt(data_efficacy) %>%
tab_options(
container.width = 800
)
#> The following rows of the given dataset have no format applied to them 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70
#> Multiple param listed for the same group/label values.
#> The following frmt_structures may be missing from the body_plan
#> or the order may need to be changed:
#> - `frmt_structure(group_val = "Baseline", label_val = "Median (Range)", frmt_combine("{median}, {min}, {max}",median = frmt("xx"), min = frmt("xx"), max = frmt("xx")))`
#> - `frmt_structure(group_val = "Change from Baseline", label_val = "Median (Range)", frmt_combine("{median}, {min}, {max}",median = frmt("xx"), min = frmt("xx"), max = frmt("xx")))`
#> - `frmt_structure(group_val = "Week 24", label_val = "Median (Range)", frmt_combine("{median}, {min}, {max}",median = frmt("xx"), min = frmt("xx"), max = frmt("xx")))`
#> - `frmt_structure(group_val = "p-value (Xan - Placebo)", label_val = "95% CI", frmt_combine("{diff_lcl}, {diff_ucl}",diff_lcl = frmt("xx"), diff_ucl = frmt("xx")))`
#> - `frmt_structure(group_val = "p-value (Xan - Placebo)", label_val = "Diff of LS Means (SE)", frmt_combine("{diff}, {diff_se}",diff = frmt("xx"), diff_se = frmt("xx")))`
#> - `frmt_structure(group_val = "p-value (Xan High - Xan Low)", label_val = "95% CI", frmt_combine("{diff_lcl}, {diff_ucl}",diff_lcl = frmt("xx"), diff_ucl = frmt("xx")))`
#> - `frmt_structure(group_val = "p-value (Xan High - Xan Low)", label_val = "Diff of LS Means (SE)", frmt_combine("{diff}, {diff_se}",diff = frmt("xx"), diff_se = frmt("xx")))`
ord1 | ord2 | Placebo | Xanomeline Low Dose | Xanomeline High Dose | |
---|---|---|---|---|---|
Baseline | |||||
n | 1 | 1 | 79 | 81 | 74 |
Mean (SD) | 1 | 2 | 24.121780881711 | 24.4074074074074 | 21.2972972972973 |
Median (Range) | 1 | 3 | 21, 5, 61 | 21, 5, 56.7241379310345 | 18, 3, 57 |
Mean (SD) | 1 | 6 | 12.1863695136042 | 12.9224478515241 | 11.7365250390648 |
Week 24 | |||||
n | 2 | 1 | 79 | 81 | 74 |
Mean (SD) | 2 | 2 | 26.6665211697948 | 26.4027245636441 | 22.7677850264057 |
Median (Range) | 2 | 3 | 24, 5, 61.551724137931 | 25, 6, 62 | 20, 3, 61.551724137931 |
Mean (SD) | 2 | 6 | 13.7942934074663 | 13.1806548367334 | 12.4835803751227 |
Change from Baseline | |||||
n | 3 | 1 | 79 | 81 | 74 |
Mean (SD) | 3 | 2 | 2.54474028808381 | 1.9953171562367 | 1.47048772910842 |
Median (Range) | 3 | 3 | 2, -11, 16 | 2, -11, 17 | 1, -7, 13 |
Mean (SD) | 3 | 6 | 5.80389919656815 | 5.55278623671741 | 4.26238487169685 |
p-value (Dose Response) | 4 | 4 | 0.2447056738685 | ||
p-value (Xan - Placebo) | 5 | 4 | 0.568846971341775 | 0.232641095885767 | |
Diff of LS Means (SE) | 5 | 5 | -0.466782357500736, 0.818042222283683 | -1.00601359773133, 0.840529356750352 | |
95% CI | 5 | 6 | -2.07898454398439, 1.14541982898292 | -2.66253355457861, 0.650506359115944 | |
p-value (Xan High - Xan Low) | 6 | 4 | 0.51964487082863 | ||
Diff of LS Means (SE) | 6 | 5 | -0.539231240230598, 0.836108901551478 | ||
95% CI | 6 | 6 | -2.18703933925105, 1.10857685878985 |
Through judicious use of body_plan
’s frmt
,
frmt_combine
, and frmt_when
, we can
conditionally format each of the different pieces of results. For the
summary statistics, we have the number of observations (n), the mean and
standard deviation (mean, sd), and the median and range (median, min,
max). For the models, we have the p-value (p.value) and the least
squares mean difference (diff) as well as its associated standard error
(diff_se) and 95% confidence interval (diff_lcl, diff_ucl).
The label
column indicates which row the various
measures belong on. First, let’s format the stand-alone values: n and
p-value. Notice that n always sits on a row labelled “n”; therefore we
can reference it by label_val or param name in the
frmt_structure
. Our p-values have several different label
values so it is more convenient to format them according to their param
name in the frmt_structure
.
tfrmt(
group = group,
label = label,
column = column,
param = param,
value = value,
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = "n",
frmt("xx")), # we could also do: label_val = ".default", n = frmt("xx")
frmt_structure(group_val = ".default", label_val = ".default",
p.value = frmt_when("<0.001" ~ "<0.001",
">0.99" ~ ">0.99",
TRUE ~ frmt("x.xxx", missing = " ")))
)
) %>%
print_to_gt(data_efficacy) %>%
tab_options(
container.width = 800
)
#> The following rows of the given dataset have no format applied to them 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 58, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70
#> Multiple param listed for the same group/label values.
#> The following frmt_structures may be missing from the body_plan
#> or the order may need to be changed:
#> - `frmt_structure(group_val = "Baseline", label_val = "Median (Range)", frmt_combine("{median}, {min}, {max}",median = frmt("xx"), min = frmt("xx"), max = frmt("xx")))`
#> - `frmt_structure(group_val = "Change from Baseline", label_val = "Median (Range)", frmt_combine("{median}, {min}, {max}",median = frmt("xx"), min = frmt("xx"), max = frmt("xx")))`
#> - `frmt_structure(group_val = "Week 24", label_val = "Median (Range)", frmt_combine("{median}, {min}, {max}",median = frmt("xx"), min = frmt("xx"), max = frmt("xx")))`
#> - `frmt_structure(group_val = "p-value (Xan - Placebo)", label_val = "95% CI", frmt_combine("{diff_lcl}, {diff_ucl}",diff_lcl = frmt("xx"), diff_ucl = frmt("xx")))`
#> - `frmt_structure(group_val = "p-value (Xan - Placebo)", label_val = "Diff of LS Means (SE)", frmt_combine("{diff}, {diff_se}",diff = frmt("xx"), diff_se = frmt("xx")))`
#> - `frmt_structure(group_val = "p-value (Xan High - Xan Low)", label_val = "95% CI", frmt_combine("{diff_lcl}, {diff_ucl}",diff_lcl = frmt("xx"), diff_ucl = frmt("xx")))`
#> - `frmt_structure(group_val = "p-value (Xan High - Xan Low)", label_val = "Diff of LS Means (SE)", frmt_combine("{diff}, {diff_se}",diff = frmt("xx"), diff_se = frmt("xx")))`
ord1 | ord2 | Placebo | Xanomeline Low Dose | Xanomeline High Dose | |
---|---|---|---|---|---|
Baseline | |||||
n | 1 | 1 | 79 | 81 | 74 |
Mean (SD) | 1 | 2 | 24.121780881711 | 24.4074074074074 | 21.2972972972973 |
Median (Range) | 1 | 3 | 21, 5, 61 | 21, 5, 56.7241379310345 | 18, 3, 57 |
Mean (SD) | 1 | 6 | 12.1863695136042 | 12.9224478515241 | 11.7365250390648 |
Week 24 | |||||
n | 2 | 1 | 79 | 81 | 74 |
Mean (SD) | 2 | 2 | 26.6665211697948 | 26.4027245636441 | 22.7677850264057 |
Median (Range) | 2 | 3 | 24, 5, 61.551724137931 | 25, 6, 62 | 20, 3, 61.551724137931 |
Mean (SD) | 2 | 6 | 13.7942934074663 | 13.1806548367334 | 12.4835803751227 |
Change from Baseline | |||||
n | 3 | 1 | 79 | 81 | 74 |
Mean (SD) | 3 | 2 | 2.54474028808381 | 1.9953171562367 | 1.47048772910842 |
Median (Range) | 3 | 3 | 2, -11, 16 | 2, -11, 17 | 1, -7, 13 |
Mean (SD) | 3 | 6 | 5.80389919656815 | 5.55278623671741 | 4.26238487169685 |
p-value (Dose Response) | 4 | 4 | 0.245 | ||
p-value (Xan - Placebo) | 5 | 4 | 0.569 | 0.233 | |
Diff of LS Means (SE) | 5 | 5 | -0.466782357500736, 0.818042222283683 | -1.00601359773133, 0.840529356750352 | |
95% CI | 5 | 6 | -2.07898454398439, 1.14541982898292 | -2.66253355457861, 0.650506359115944 | |
p-value (Xan High - Xan Low) | 6 | 4 | 0.520 | ||
Diff of LS Means (SE) | 6 | 5 | -0.539231240230598, 0.836108901551478 | ||
95% CI | 6 | 6 | -2.18703933925105, 1.10857685878985 |
Next, the remaining param values are combined in twos or threes.
Therefore, we use the frmt_combine
utility to achieve
desired formatting:
tfrmt(
group = group,
label = label,
column = column,
param = param,
value = value,
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = "n",
frmt("xx")), # we could also do: label_val = ".default", n = frmt("xx")
frmt_structure(group_val = ".default", label_val = ".default",
p.value = frmt_when("<0.001" ~ "<0.001",
">0.99" ~ ">0.99",
TRUE ~ frmt("x.xxx", missing = " "))),
frmt_structure(group_val = ".default", label_val = "Median (Range)",
frmt_combine("{median} ({min};{max})",
median = frmt("xx.x"),
min = frmt("xx"),
max = frmt("xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "Mean (SD)",
frmt_combine("{mean} ({sd})",
mean = frmt("xx.x"),
sd = frmt("xx.xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "Diff of LS Means (SE)",
frmt_combine("{diff} ({diff_se})",
diff = frmt("xx.x"),
diff_se = frmt("xx.xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "95% CI",
frmt_combine("({diff_lcl};{diff_ucl})",
diff_lcl = frmt("xx.x"),
diff_ucl = frmt("xx.x"), missing = " "))
)
) %>%
print_to_gt(data_efficacy) %>%
tab_options(
container.width = 800
)
ord1 | ord2 | Placebo | Xanomeline Low Dose | Xanomeline High Dose | |
---|---|---|---|---|---|
Baseline | |||||
n | 1 | 1 | 79 | 81 | 74 |
Mean (SD) | 1 | 2 | 24.1 (12.19) | 24.4 (12.92) | 21.3 (11.74) |
Median (Range) | 1 | 3 | 21.0 ( 5;61) | 21.0 ( 5;57) | 18.0 ( 3;57) |
Week 24 | |||||
n | 2 | 1 | 79 | 81 | 74 |
Mean (SD) | 2 | 2 | 26.7 (13.79) | 26.4 (13.18) | 22.8 (12.48) |
Median (Range) | 2 | 3 | 24.0 ( 5;62) | 25.0 ( 6;62) | 20.0 ( 3;62) |
Change from Baseline | |||||
n | 3 | 1 | 79 | 81 | 74 |
Mean (SD) | 3 | 2 | 2.5 ( 5.80) | 2.0 ( 5.55) | 1.5 ( 4.26) |
Median (Range) | 3 | 3 | 2.0 (-11;16) | 2.0 (-11;17) | 1.0 (-7;13) |
p-value (Dose Response) | 4 | 4 | 0.245 | ||
p-value (Xan - Placebo) | 5 | 4 | 0.569 | 0.233 | |
Diff of LS Means (SE) | 5 | 5 | -0.5 ( 0.82) | -1.0 ( 0.84) | |
95% CI | 5 | 6 | (-2.1; 1.1) | (-2.7; 0.7) | |
p-value (Xan High - Xan Low) | 6 | 4 | 0.520 | ||
Diff of LS Means (SE) | 6 | 5 | -0.5 ( 0.84) | ||
95% CI | 6 | 6 | (-2.2; 1.1) |
Now that our values are all formatted correctly, we can make sure the
table is sorted appropriately by passing our order columns to
sorting_cols
. We can also drop these order columns from the
final display using col_plan
.
tfrmt(
group = group,
label = label,
column = column,
param = param,
value = value,
sorting_cols = c(ord1, ord2),
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = "n",
frmt("xx")), # we could also do: label_val = ".default", n = frmt("xx")
frmt_structure(group_val = ".default", label_val = ".default",
p.value = frmt_when("<0.001" ~ "<0.001",
">0.99" ~ ">0.99",
TRUE ~ frmt("x.xxx", missing = " "))),
frmt_structure(group_val = ".default", label_val = "Median (Range)",
frmt_combine("{median} ({min};{max})",
median = frmt("xx.x"),
min = frmt("xx"),
max = frmt("xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "Mean (SD)",
frmt_combine("{mean} ({sd})",
mean = frmt("xx.x"),
sd = frmt("xx.xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "Diff of LS Means (SE)",
frmt_combine("{diff} ({diff_se})",
diff = frmt("xx.x"),
diff_se = frmt("xx.xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "95% CI",
frmt_combine("({diff_lcl};{diff_ucl})",
diff_lcl = frmt("xx.x"),
diff_ucl = frmt("xx.x"), missing = " "))
),
col_plan = col_plan(
group, label, Placebo, contains("Low"), contains("High"), -starts_with("ord")
)
) %>%
print_to_gt(data_efficacy) %>%
tab_options(
container.width = 800
)
Placebo | Xanomeline Low Dose | Xanomeline High Dose | |
---|---|---|---|
Baseline | |||
n | 79 | 81 | 74 |
Mean (SD) | 24.1 (12.19) | 24.4 (12.92) | 21.3 (11.74) |
Median (Range) | 21.0 ( 5;61) | 21.0 ( 5;57) | 18.0 ( 3;57) |
Week 24 | |||
n | 79 | 81 | 74 |
Mean (SD) | 26.7 (13.79) | 26.4 (13.18) | 22.8 (12.48) |
Median (Range) | 24.0 ( 5;62) | 25.0 ( 6;62) | 20.0 ( 3;62) |
Change from Baseline | |||
n | 79 | 81 | 74 |
Mean (SD) | 2.5 ( 5.80) | 2.0 ( 5.55) | 1.5 ( 4.26) |
Median (Range) | 2.0 (-11;16) | 2.0 (-11;17) | 1.0 (-7;13) |
p-value (Dose Response) | 0.245 | ||
p-value (Xan - Placebo) | 0.569 | 0.233 | |
Diff of LS Means (SE) | -0.5 ( 0.82) | -1.0 ( 0.84) | |
95% CI | (-2.1; 1.1) | (-2.7; 0.7) | |
p-value (Xan High - Xan Low) | 0.520 | ||
Diff of LS Means (SE) | -0.5 ( 0.84) | ||
95% CI | (-2.2; 1.1) |
Notice that our row labels are not quite right. First, we have a bit
of a hierarchy with the label
values nested under the
group
values, and it would be nice to add some indentation
to make the nesting more obvious. Also, in some cases, the
group
values also contain summary data, which means the ARD
contains a matching group
and label
value. For
summary rows, we want to suppress the printing of the extra group-level
header, and display the summary data in-line. The
row_grp_plan
can help us with both via the
row_grp_loc
argument:
tfrmt(
group = group,
label = label,
column = column,
param = param,
value = value,
sorting_cols = c(ord1, ord2),
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = "n",
frmt("xx")), # we could also do: label_val = ".default", n = frmt("xx")
frmt_structure(group_val = ".default", label_val = ".default",
p.value = frmt_when("<0.001" ~ "<0.001",
">0.99" ~ ">0.99",
TRUE ~ frmt("x.xxx", missing = " "))),
frmt_structure(group_val = ".default", label_val = "Median (Range)",
frmt_combine("{median} ({min};{max})",
median = frmt("xx.x"),
min = frmt("xx"),
max = frmt("xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "Mean (SD)",
frmt_combine("{mean} ({sd})",
mean = frmt("xx.x"),
sd = frmt("xx.xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "Diff of LS Means (SE)",
frmt_combine("{diff} ({diff_se})",
diff = frmt("xx.x"),
diff_se = frmt("xx.xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "95% CI",
frmt_combine("({diff_lcl};{diff_ucl})",
diff_lcl = frmt("xx.x"),
diff_ucl = frmt("xx.x"), missing = " "))
),
col_plan = col_plan(
group, label, Placebo, contains("Low"), contains("High"), -starts_with("ord")
),
row_grp_plan = row_grp_plan(
label_loc = element_row_grp_loc(location = "indented")
)
) %>%
print_to_gt(data_efficacy) %>%
tab_options(
container.width = 800
)
Placebo | Xanomeline Low Dose | Xanomeline High Dose | |
---|---|---|---|
Baseline | |||
n | 79 | 81 | 74 |
Mean (SD) | 24.1 (12.19) | 24.4 (12.92) | 21.3 (11.74) |
Median (Range) | 21.0 ( 5;61) | 21.0 ( 5;57) | 18.0 ( 3;57) |
Week 24 | |||
n | 79 | 81 | 74 |
Mean (SD) | 26.7 (13.79) | 26.4 (13.18) | 22.8 (12.48) |
Median (Range) | 24.0 ( 5;62) | 25.0 ( 6;62) | 20.0 ( 3;62) |
Change from Baseline | |||
n | 79 | 81 | 74 |
Mean (SD) | 2.5 ( 5.80) | 2.0 ( 5.55) | 1.5 ( 4.26) |
Median (Range) | 2.0 (-11;16) | 2.0 (-11;17) | 1.0 (-7;13) |
p-value (Dose Response) | 0.245 | ||
p-value (Xan - Placebo) | 0.569 | 0.233 | |
Diff of LS Means (SE) | -0.5 ( 0.82) | -1.0 ( 0.84) | |
95% CI | (-2.1; 1.1) | (-2.7; 0.7) | |
p-value (Xan High - Xan Low) | 0.520 | ||
Diff of LS Means (SE) | -0.5 ( 0.84) | ||
95% CI | (-2.2; 1.1) |
Almost done! Notice that the spec also contains empty rows after
different groups of data. We can mimic this behavior by passing
row_grp_structure
objects in our row_grp_plan
.
These objects define “blocks” of rows and describe how to format them.
In this case, we want to add a post space after specific blocks of data.
We can reference the locations of each block based on the values of the
group
variable.
tfrmt(
group = group,
label = label,
column = column,
param = param,
value = value,
sorting_cols = c(ord1, ord2),
body_plan = body_plan(
frmt_structure(group_val = ".default", label_val = "n",
frmt("xx")), # we could also do: label_val = ".default", n = frmt("xx")
frmt_structure(group_val = ".default", label_val = ".default",
p.value = frmt_when("<0.001" ~ "<0.001",
">0.99" ~ ">0.99",
TRUE ~ frmt("x.xxx", missing = " "))),
frmt_structure(group_val = ".default", label_val = "Median (Range)",
frmt_combine("{median} ({min};{max})",
median = frmt("xx.x"),
min = frmt("xx"),
max = frmt("xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "Mean (SD)",
frmt_combine("{mean} ({sd})",
mean = frmt("xx.x"),
sd = frmt("xx.xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "Diff of LS Means (SE)",
frmt_combine("{diff} ({diff_se})",
diff = frmt("xx.x"),
diff_se = frmt("xx.xx"), missing = " ")),
frmt_structure(group_val = ".default", label_val = "95% CI",
frmt_combine("({diff_lcl};{diff_ucl})",
diff_lcl = frmt("xx.x"),
diff_ucl = frmt("xx.x"), missing = " "))
),
col_plan = col_plan(
group, label, Placebo, contains("Low"), contains("High"), -starts_with("ord")
),
row_grp_plan = row_grp_plan(
row_grp_structure(group_val = list(group="Change from Baseline"),
element_block(post_space = " ")),
row_grp_structure(group_val = list(group="p-value (Dose Response)"),
element_block(post_space = " ")),
row_grp_structure(group_val = list(group="p-value (Xan - Placebo)"),
element_block(post_space = " ")),
label_loc = element_row_grp_loc(location = "indented")
)
) %>%
print_to_gt(data_efficacy) %>%
tab_options(
container.width = 800
)
Placebo | Xanomeline Low Dose | Xanomeline High Dose | |
---|---|---|---|
Baseline | |||
n | 79 | 81 | 74 |
Mean (SD) | 24.1 (12.19) | 24.4 (12.92) | 21.3 (11.74) |
Median (Range) | 21.0 ( 5;61) | 21.0 ( 5;57) | 18.0 ( 3;57) |
Week 24 | |||
n | 79 | 81 | 74 |
Mean (SD) | 26.7 (13.79) | 26.4 (13.18) | 22.8 (12.48) |
Median (Range) | 24.0 ( 5;62) | 25.0 ( 6;62) | 20.0 ( 3;62) |
Change from Baseline | |||
n | 79 | 81 | 74 |
Mean (SD) | 2.5 ( 5.80) | 2.0 ( 5.55) | 1.5 ( 4.26) |
Median (Range) | 2.0 (-11;16) | 2.0 (-11;17) | 1.0 (-7;13) |
p-value (Dose Response) | 0.245 | ||
p-value (Xan - Placebo) | 0.569 | 0.233 | |
Diff of LS Means (SE) | -0.5 ( 0.82) | -1.0 ( 0.84) | |
95% CI | (-2.1; 1.1) | (-2.7; 0.7) | |
p-value (Xan High - Xan Low) | 0.520 | ||
Diff of LS Means (SE) | -0.5 ( 0.84) | ||
95% CI | (-2.2; 1.1) |
There we have it, our efficacy table is complete!