Overview
Each endpoint needs to be generated from a single analysis data set
containing information from one or more ADaM data sets. Each analysis
data set is created by a custom ADaM function written by the trial
programmer that is referenced in the endpoint specification via the
data_prepare
parameter. The ADaM function contains
instructions to what ADaM data sets to join, how to join, and what
custom variables e.g., new groupings, to create (if any).
There are three requirements for the ADaM function:
- It must have exactly one input argument
study_metadata
which is an endpoint specification parameter, preferably a 1-element list, that contains any relevant information about the study that may be used to read the ADaM data sets. If no such information is needed, then leavestudy_metadata
unused in the function and set it as an emptylist()
in the endpoint specification. - It must each return a
data.table
object. If you do not work indata.table
, you can do this by converting yourtibble
ordata.frame
object to adata.table
object at the end of the function viadata.table::as.data.table(my_data_frame)
. - The returned table must contain all the ADAM variables (and derived
variables) that are mentioned in the endpoint specification and also the
subject ID variable
USUBJID
.
In summary, the analysis data set generation is controlled with the following two parameters in the endpoint specification:
- data_prepare: Reference to a custom function that returns a single consolidated analysis table that contains all ADaM data needed in the endpoint.
- study_metadata: Object containing study specifics that are relevant for reading the ADAM data. Must be parsed as the input to the ADaM and ADSL functions. May be empty if not needed.
Examples
Ex 1.1
Here is an example of an ADAM function that first reads the
ADSL
data table from {pharmaverseadam}, filters it down to
two treatment arms, and enriches it with a derived variable. Then it
merges the enriched ADSL with ADAE from {pharmaverseadam} and return a
single table with all the ADaM information from ADSL
and
ADAE
:
# Example of ADaM function that merges information from ADSL and ADAE
mk_adam_ex1_1 <- function(study_metadata) {
# Read ADSL from {pharmaverseadam}
adsl <- data.table::as.data.table(pharmaverseadam::adsl)
# Filter treatment arms
adsl <- adsl[adsl$TRT01A %in% c('Placebo', 'Xanomeline High Dose')]
# New derived ADSL variable
adsl[, AGEGR2 := data.table::fcase(AGE < 70, "AGE < 70",
AGE >= 70, "AGE >= 70")]
# Read ADAE from {pharmaverseadam}
adae <- data.table::as.data.table(pharmaverseadam::adae)
# Merge ADSL and ADAE
adae_out <-
merge(adsl, adae[, c(setdiff(names(adae), names(adsl)), "USUBJID"), with =
F], by = "USUBJID", all = TRUE)
return(adae_out)
}
Ex 1.2
You might also have cases where information from several ADAM tables
are required in your endpoint. Here is an example that returns the same
ADaM information as the example above with the addition of the baseline
body weight extracted from ADVS
. So information from three
ADaM tables are merged and returned in a single analysis data set:
# Example of ADaM function that merges information from three ADaM tables
mk_adam_ex1_2 <- function(study_metadata) {
# Read ADSL from {pharmaverseadam}
adsl <- data.table::as.data.table(pharmaverseadam::adsl)
# Filter treatment arms
adsl <- adsl[adsl$TRT01A %in% c('Placebo', 'Xanomeline High Dose')]
# New derived ADSL variable
adsl[, AGEGR2 := data.table::fcase(AGE < 70, "AGE < 70",
AGE >= 70, "AGE >= 70")]
# Read ADAE from {pharmaverseadam}
adae <- data.table::as.data.table(pharmaverseadam::adae)
# Read ADVS from {pharmaverseadam}
advs <- data.table::as.data.table(pharmaverseadam::advs)
# Identify baseline body weight
advs_bw <- advs[advs$PARAMCD == "WEIGHT" & advs$VISIT == "BASELINE"]
# Create new variable bw_baseline
advs_bw[["bw_baseline"]] <- advs_bw[["AVAL"]]
# Merge ADSL, ADAE and baseline body weight from ADVS
ax_out <-
merge(adsl, adae[, c(setdiff(names(adae), names(adsl)), "USUBJID"), with = F],
by = "USUBJID", all.x = TRUE) |>
merge(x=_, advs_bw[, c("bw_baseline", "USUBJID")], by = "USUBJID", all.x = TRUE)
return(ax_out)
}
Ex 1.3
The ADaM functions, once defined, need to be linked to the
corresponding endpoint specifications via the data_prepare parameter.
The creation of each endpoint specification is facilitated by the
mk_endpoint_str function wherein this data_prepare parameter is
established. In the following example, the mk_adam_ex1_2
function is utilized to produce the analysis data intended for an
endpoint.
# Example of endpoint specification of ADaM function.
# The dots must be replaced with other required parameters.
ep_spec_ex1_3 <- chef::mk_endpoint_str(
data_prepare = mk_adam_ex1_2,
...)