Introduction to Chevron
Adrian Waddell
2022-10-21
chevron.Rmd
Introduction
The chevron
R package provides functions to produce
standard tables, listings and graphs (TLGs) used to analyze and report
clinical trials data. The ensemble of function used to produce a
particular output are stored in an S4
object of virtual
class chevron_tlg
. Each type of output are associated with
a specific class: chevron_t
for tables,
chevron_l
for listings and chevron_g
for
graphs.
Each standard output is associated with one
chevron_tlg
object. They contain the following
objects in separate slots:
- A
main
function also refereed to as TLG-function. - A
preprocess
function. - A
postprocess
function - A
adam_datasets
character vector of the name of theAdAM
datasets required to create the output.
TLG-functions
The TLG-functions in chevron
use other packages
to produce the final outputs, for example rtables
and
tern
are used to create tables, ggplot2
,
lattice
, and grid
are used to create graphs,
rlistings
to create listings.
TLG-functions in chevron
such as
dmt01_main
, aet02_main
,
aet02_main
have the following properties:
- they produce a narrow defined output (currently standards in Roche
GDS
). Note, that the naming convention<gds template id>_main
indicates that a RocheGDS
defined standard may have different implementations. Or, alternatively, aGDS
template id can be regarded as a guideline and the function name inchevron
as a standard. - have, if possible, few arguments to modify the standard. Generally, arguments may change the structure of the table (arm variable, which variables are summarized) and also parameterize the cell content (i.e. alpha-level for p-value).
- have always the first argument
adam_db
which is the collection ofADaM
datasets (ADSL
,ADAE
,ADRS
, etc.). Please read the Theadam_db
Argument vignette in this package for more details.
preprocessing
The preprocess functions in chevron
use
base
, dplyr
and dunlin
packages
to process input data object and turn them into a suitable input for
TLG-functions.
preprocess in chevron such as dmt01_pre
,
aet02_pre
, aet02_pre
have the following
properties:
- they return a
list
ofdata.frame
object amenable to processing by a TLG-functions. message. - have very few arguments to modify the standard.
- have always the first argument
adam_db
which is the collection ofADaM
datasets (ADSL
,ADAE
,ADRS
, etc.). Please read the Theadam_db
Argument vignette in this package for more details.
Please note that the ultimate responsible person of the preprocessing
functions is the end user. The provided preprocessing function is only a
template and users could modify depending on their need/data. This
preprocessing function will be printed to allow modification in script
generated in citril
.
Example AET02
For example, the GDS
template aet02
is
implemented in chevron
with the chevropn_tlg
objects that have the name aet02
.
We first load the data as a list
of
data.frame
, where each table represents a domain.
library(chevron)
#> Registered S3 method overwritten by 'tern':
#> method from
#> tidy.glm broom
data(syn_data, package = "chevron")
A the aet02
output is then created as follows:
run(aet02, syn_data)
#> MedDRA System Organ Class A: Drug X B: Placebo C: Combination
#> MedDRA Preferred Term (N=134) (N=134) (N=132)
#> ———————————————————————————————————————————————————————————————————————————————————————————————————————
#> Total number of patients with at least one adverse event 122 (91.0%) 123 (91.8%) 120 (90.9%)
#> Overall total number of events 609 622 703
#> cl A.1
#> Total number of patients with at least one adverse event 78 (58.2%) 75 (56.0%) 89 (67.4%)
#> Total number of events 132 130 160
#> dcd A.1.1.1.1 50 (37.3%) 45 (33.6%) 63 (47.7%)
#> dcd A.1.1.1.2 48 (35.8%) 48 (35.8%) 50 (37.9%)
#> cl B.2
#> Total number of patients with at least one adverse event 79 (59.0%) 74 (55.2%) 85 (64.4%)
#> Total number of events 129 138 143
#> dcd B.2.2.3.1 48 (35.8%) 54 (40.3%) 51 (38.6%)
#> dcd B.2.1.2.1 49 (36.6%) 44 (32.8%) 52 (39.4%)
#> cl D.1
#> Total number of patients with at least one adverse event 79 (59.0%) 67 (50.0%) 80 (60.6%)
#> Total number of events 127 106 135
#> dcd D.1.1.1.1 50 (37.3%) 42 (31.3%) 51 (38.6%)
#> dcd D.1.1.4.2 48 (35.8%) 42 (31.3%) 50 (37.9%)
#> cl D.2
#> Total number of patients with at least one adverse event 47 (35.1%) 58 (43.3%) 57 (43.2%)
#> Total number of events 62 72 74
#> dcd D.2.1.5.3 47 (35.1%) 58 (43.3%) 57 (43.2%)
#> cl B.1
#> Total number of patients with at least one adverse event 47 (35.1%) 49 (36.6%) 43 (32.6%)
#> Total number of events 56 60 62
#> dcd B.1.1.1.1 47 (35.1%) 49 (36.6%) 43 (32.6%)
#> cl C.2
#> Total number of patients with at least one adverse event 35 (26.1%) 48 (35.8%) 55 (41.7%)
#> Total number of events 48 53 65
#> dcd C.2.1.2.1 35 (26.1%) 48 (35.8%) 55 (41.7%)
#> cl C.1
#> Total number of patients with at least one adverse event 43 (32.1%) 46 (34.3%) 43 (32.6%)
#> Total number of events 55 63 64
#> dcd C.1.1.1.3 43 (32.1%) 46 (34.3%) 43 (32.6%)
The function associated with a particular slot can be retrieved with
the corresponding method: main
, lyt
,
preprocess
postprocess
and
datasets
.
main(aet02)
#> function (adam_db, arm_var = "ACTARM", row_split_var = "AEBODSYS",
#> lbl_overall = NULL, ...)
#> {
#> assert_all_tablenames(adam_db, "adsl", "adae")
#> checkmate::assert_character(row_split_var, null.ok = TRUE)
#> checkmate::assert_string(lbl_overall, null.ok = TRUE)
#> checkmate::assert_string(arm_var)
#> assert_valid_variable(adam_db$adsl, c("USUBJID", arm_var),
#> types = list(c("character", "factor")))
#> assert_valid_variable(adam_db$adae, c(arm_var, row_split_var,
#> "AEDECOD"), types = list(c("character", "factor")))
#> assert_valid_variable(adam_db$adae, "USUBJID", empty_ok = TRUE,
#> types = list(c("character", "factor")))
#> assert_valid_var_pair(adam_db$adsl, adam_db$adae, arm_var)
#> lbl_row_split <- var_labels_for(adam_db$adae, row_split_var)
#> lbl_aedecod <- var_labels_for(adam_db$adae, "AEDECOD")
#> lyt <- aet02_lyt(arm_var = arm_var, lbl_overall = lbl_overall,
#> row_split_var = row_split_var, lbl_row_split = lbl_row_split,
#> lbl_aedecod = lbl_aedecod)
#> tbl <- build_table(lyt, adam_db$adae, alt_counts_df = adam_db$adsl)
#> tbl
#> }
#> <bytecode: 0x55baf6250b80>
#> <environment: namespace:chevron>
These are standard functions that can be used on their own.
res <- preprocess(aet02)(syn_data)
# or
foo <- aet02@preprocess
res <- foo(syn_data)
str(res, max.level = 0)
#> List of 19
chevron_tlg
object customization
In some instances it is useful to customize the
chevron_tlg
object, for example by changing the pre
processing functions in script generated. Please modify the code
directly inside the pre_fun
, and make sure the function
returns a named list of data frames. Please be careful about the
argument names. The default argument of pre
functions will
be override by the argument in spec.
Custom chevron_tlg
object creation
In some cases, you may want to create a new chevron_tlg
template. To create a chevron_tlg
object from scratch, use
the provided constructors corresponding to the desired output:
-
chevron_t()
for tables. -
chevron_l()
for listings. -
chevron_g()
for graphs.
library(rtables)
library(tern)
my_template <- chevron_t(
main = "<your main function to build the table>",
preprocess = "<your pre function to process the data>",
postprocess = "<your post function to add custom sorting>",
adam_datasets = c("adsl")
)
run(my_template, syn_data)
Note that to ensure the correct execution of the run
function, the name of the first argument of the main
function must be adam_db
; the input list
of
data.frame
object to pre-process. The name of the first
argument of the preprocess
function must be
adam_db
; the input dm
object to create
TLG
output and finally, the name of the first argument of
the postprocess
function must be tlg
, the
input TableTree
object to post-process. Validation criteria
enforce these rules upon creation of a chevron_tlg
object.