Layouts in Chevron
layouts.Rmd
Introduction
The chevron
R package has a collection of functions that
create standard tables, listings, and graphs (TLGs). These functions are
referred in chevron
as TLG-functions. A subset of
these TLG-functions create tables. Tables are created using the
rtables
package. rtables
has the context of
table layouts, i.e. pre-data table cell-derivation instructions. For
example:
library(rtables)
#> Loading required package: magrittr
#> Loading required package: formatters
lyt <- basic_table() %>%
split_cols_by("ARM") %>%
analyze("AGE", mean)
lyt
#> A Pre-data Table Layout
#>
#> Column-Split Structure:
#> ARM (lvls)
#>
#> Row-Split Structure:
#> AGE (** analysis **)
These layout contain all the cell-value derivation information and can be used and reused for different data
adsl <- data.frame(
ARM = factor(sample(c("ARM A", "ARM B"), 100, TRUE)),
AGE = runif(100, 20, 90),
COUNTRY = factor(sample(c("CHN", "USA", "BRA", "RUS"), 100, TRUE))
)
build_table(lyt, adsl)
#> ARM A ARM B
#> ——————————————————————————————————————————
#> mean 54.8783647256938 51.0443174518625
build_table(lyt, adsl[adsl$COUNTRY == "RUS", ])
#> ARM A ARM B
#> ——————————————————————————————————————————
#> mean 52.0701733764145 41.0643042990176
Hence these layouts define a table pre-data. That is, the layout
functions in chevron
do never take any data as an argument.
Note that pruning and sorting are currently not performed in the layout
space in rtables
but rather on the actual table
objects.
Also, layouts allow for certain queries such as which variables are required to build the table using the given layout:
rtables::vars_in_layout(lyt)
#> [1] "ARM" "AGE"
So in chevron
when creating tables we always do the
explicit layout creation in the *_lyt
functions. For
example for aet02_1
we have the layout function:
library(chevron)
#> Registered S3 method overwritten by 'tern':
#> method from
#> tidy.glm broom
aet02_1_lyt
#> function (arm_var, lbl_overall, lbl_aebodsys, lbl_aedecod, deco)
#> {
#> basic_table_deco(deco) %>% split_cols_by(var = arm_var) %>%
#> add_colcounts() %>% ifneeded_add_overall_col(lbl_overall) %>%
#> summarize_num_patients(var = "USUBJID", .stats = c("unique",
#> "nonunique"), .labels = c(unique = "Total number of patients with at least one adverse event",
#> nonunique = "Overall total number of events")) %>%
#> split_rows_by("AEBODSYS", child_labels = "visible", labels_var = "AEBODSYS",
#> nested = FALSE, indent_mod = -1L, split_fun = drop_split_levels,
#> label_pos = "topleft", split_label = lbl_aebodsys) %>%
#> summarize_num_patients(var = "USUBJID", .stats = c("unique",
#> "nonunique"), .labels = c(unique = "Total number of patients with at least one adverse event",
#> nonunique = "Total number of events")) %>% count_occurrences(vars = "AEDECOD",
#> .indent_mods = -1L) %>% append_topleft(paste0(" ", lbl_aedecod))
#> }
#> <bytecode: 0x563d4d1f3988>
#> <environment: namespace:chevron>
Note that the aet02_1_lyt
function returns a concise
description on how tern
and rtables
can be
used to create the cell values of the tables. The table creation
function then does then use the *_lyt
function and builds
the table using build_table
and the data given in
adam_db
as shown next:
aet02_1_main
#> function (adam_db, arm_var = "ACTARM", lbl_overall = NULL, lbl_aebodsys = "MedDRA System Organ Class",
#> lbl_aedecod = "MedDRA Preferred Term", deco = std_deco("AET02"),
#> ...)
#> {
#> dbsel <- get_db_data(adam_db, "adsl", "adae")
#> assert_colnames(adam_db$adae, c("AEBODSYS", "AEDECOD"))
#> lyt <- aet02_1_lyt(arm_var = arm_var, lbl_overall = lbl_overall,
#> lbl_aebodsys = lbl_aebodsys, lbl_aedecod = lbl_aedecod,
#> deco = deco)
#> tbl <- build_table(lyt, dbsel$adae, alt_counts_df = dbsel$adsl)
#> tbl
#> }
#> <bytecode: 0x563d4d3645b0>
#> <environment: namespace:chevron>
Summary
- Layouts specify a tabulation an cell-values derivation pre-data
- these layouts are useful to understand how table is created and what variables are required in the data to create a table using the layout
- the table creation functions focus the main part of their code on building, sorting and pruning the table
- Headers and footers are taken by default from the standards. They
can be specified with the
deco
argument. Note that we currently do not have all of the data base for standard headers and footers imported inchevron
.