# Creating a BDS Exposure ADaM

# Introduction

This article describes creating an Exposure ADaM using the BDS structure. Examples are currently presented using an underlying `EX` domain where the `EX` domain represents data as collected on the CRF and the `ADEX` ADaM is output. However, the examples can be applied to situations where an `EC` domain is used as input and/or `ADEC` or another exposure ADaM is created.

There are many different approaches to modeling exposure data. This vignette gives examples of creating `PARAMCD` and `AVAL` combinations using exposure data. This vignette is not meant to be a guide or standard for the structure of exposure analysis datasets.

Note: All examples assume CDISC SDTM and/or ADaM format as input unless otherwise specified.

# Programming Workflow

- Read in Data
- Derive/Impute Numeric Date/Time and Analysis Day (`ADT`, `ADTM`, `ADY`, `ADTF`, `ATMF`)
- Compute Duration for a Record
- Create 1:1 Mapping Records
- Create Summary Records
- Assign `PARAMCD`, `PARAMN`, etc. from Reference Tables
- Derive Categorization Variables (`AVALCATy`)
- Assign `ASEQ`
- Add ADSL variables
- Add Labels and Attributes

## Read in Data

To start, all data frames needed for the creation of `ADEX` should be read into the environment. This will be a company specific process. Some of the data frames needed may be `EX` and `ADSL`.

For example purpose, the CDISC Pilot SDTM and ADaM datasets—which are included in `{pharmaversesdtm}`—are used.

    library(admiral)
    library(dplyr, warn.conflicts = FALSE)
    library(pharmaversesdtm)
    library(lubridate)
    library(stringr)
    library(tibble)

    ex <- pharmaversesdtm::ex
    adsl <- admiral::admiral_adsl

    ex <- convert_blanks_to_na(ex)

At this step, it may be useful to join `ADSL` to your `EX` domain as well. Only the `ADSL` variables used for derivations are selected at this step. The rest of the relevant `ADSL` variables would be added later.

    adsl_vars <- exprs(TRTSDT, TRTSDTM, TRTEDT, TRTEDTM)

    adex <- derive_vars_merged(
      ex,
      dataset_add = adsl,
      new_vars = adsl_vars,
      by_vars = get_admiral_option("subject_keys")
    )

USUBJID | EXTRT | EXDOSE | EXDOSFRQ | VISIT | EXSTDTC | EXENDTC | TRTSDTM | TRTEDTM
--- | --- | --- | --- | --- | --- | --- | --- | ---
01-701-1015 | PLACEBO | 0 | QD | BASELINE | 2014-01-02 | 2014-01-16 | 2014-01-02 | 2014-07-02 23:59:59
01-701-1015 | PLACEBO | 0 | QD | WEEK 2 | 2014-01-17 | 2014-06-18 | 2014-01-02 | 2014-07-02 23:59:59
01-701-1015 | PLACEBO | 0 | QD | WEEK 24 | 2014-06-19 | 2014-07-02 | 2014-01-02 | 2014-07-02 23:59:59
01-701-1023 | PLACEBO | 0 | QD | BASELINE | 2012-08-05 | 2012-08-27 | 2012-08-05 | 2012-09-01 23:59:59
01-701-1023 | PLACEBO | 0 | QD | WEEK 2 | 2012-08-28 | 2012-09-01 | 2012-08-05 | 2012-09-01 23:59:59
01-703-1086 | XANOMELINE | 54 | QD | BASELINE | 2012-09-02 | 2012-09-16 | 2012-09-02 | 2012-12-04 23:59:59
01-703-1086 | XANOMELINE | 54 | QD | WEEK 2 | 2012-09-17 | 2012-12-04 | 2012-09-02 | 2012-12-04 23:59:59
01-703-1096 | PLACEBO | 0 | QD | BASELINE | 2013-01-25 | 2013-02-09 | 2013-01-25 | 2013-03-16 23:59:59
01-703-1096 | PLACEBO | 0 | QD | WEEK 2 | 2013-02-10 | 2013-03-16 | 2013-01-25 | 2013-03-16 23:59:59
01-707-1037 | XANOMELINE | 54 | QD | BASELINE | 2013-12-20 | 2013-12-24 | 2013-12-20 | 2013-12-24 23:59:59

The CDISC pilot `EX` domain data does not contain a dose adjustment flag or the planned dose information. For demonstration purposes, this will be added to the data.

    adex <- adex %>%
      mutate(
        EXADJ = case_when(
          USUBJID == "01-701-1028" & VISIT %in% c("WEEK 2") ~ "ADVERSE EVENT",
          USUBJID == "01-701-1148" & VISIT %in% c("WEEK 2", "WEEK 24") ~ "MEDICATION ERROR",
          TRUE ~ NA_character_
        ),
        EXDOSE = case_when(
          USUBJID == "01-701-1028" & VISIT %in% c("WEEK 2") ~ 0,
          USUBJID == "01-701-1148" & VISIT %in% c("WEEK 2", "WEEK 24") ~ 0,
          TRUE ~ EXDOSE
        )
      ) %>%
      mutate(EXPLDOS = if_else(EXTRT == "PLACEBO", 0, 54))

    distinct(adex, EXTRT, EXPLDOS)
    #> # A tibble: 2 × 2
    #>   EXTRT      EXPLDOS
    #>   <chr>        <dbl>
    #> 1 PLACEBO          0
    #> 2 XANOMELINE      54
    count(adex, EXADJ)
    #> # A tibble: 1 × 2
    #>   EXADJ     n
    #>   <chr> <int>
    #> 1 <NA>     13

## Derive/Impute Numeric Date/Time and Analysis Day (`ADT`, `ADTM`, `ADY`, `ADTF`, `ATMF`)

The function `derive_vars_dt()` can be used to derive `ADT`. This function allows the user to impute the date as well.

Example calls:

    adex <- derive_vars_dt(adex, new_vars_prefix = "AST", dtc = EXSTDTC)
    adex <- derive_vars_dt(adex, new_vars_prefix = "AEN", dtc = EXENDTC)

USUBJID | VISIT | EXSTDTC | EXENDTC | ASTDT | AENDT
--- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | 2014-01-02 | 2014-01-16 | 2014-01-02 | 2014-01-16
01-701-1015 | WEEK 2 | 2014-01-17 | 2014-06-18 | 2014-01-17 | 2014-06-18
01-701-1015 | WEEK 24 | 2014-06-19 | 2014-07-02 | 2014-06-19 | 2014-07-02
01-701-1023 | BASELINE | 2012-08-05 | 2012-08-27 | 2012-08-05 | 2012-08-27
01-701-1023 | WEEK 2 | 2012-08-28 | 2012-09-01 | 2012-08-28 | 2012-09-01
01-703-1086 | BASELINE | 2012-09-02 | 2012-09-16 | 2012-09-02 | 2012-09-16
01-703-1086 | WEEK 2 | 2012-09-17 | 2012-12-04 | 2012-09-17 | 2012-12-04
01-703-1096 | BASELINE | 2013-01-25 | 2013-02-09 | 2013-01-25 | 2013-02-09
01-703-1096 | WEEK 2 | 2013-02-10 | 2013-03-16 | 2013-02-10 | 2013-03-16
01-707-1037 | BASELINE | 2013-12-20 | 2013-12-24 | 2013-12-20 | 2013-12-24

The next examples demonstrates the datetime imputation features available in the `derive_vars_dtm()` function, where the time is imputed as “00:00:00”:

    adex <- derive_vars_dtm(
      adex,
      dtc = EXSTDTC,
      highest_imputation = "M",
      new_vars_prefix = "AST"
    )

    adex <- derive_vars_dtm(
      adex,
      dtc = EXENDTC,
      highest_imputation = "M",
      date_imputation = "last",
      new_vars_prefix = "AEN"
    )

USUBJID | VISIT | EXSTDTC | EXENDTC | ASTDTM | AENDTM
--- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | 2014-01-02 | 2014-01-16 | 2014-01-02 | 2014-01-16
01-701-1015 | WEEK 2 | 2014-01-17 | 2014-06-18 | 2014-01-17 | 2014-06-18
01-701-1015 | WEEK 24 | 2014-06-19 | 2014-07-02 | 2014-06-19 | 2014-07-02
01-701-1023 | BASELINE | 2012-08-05 | 2012-08-27 | 2012-08-05 | 2012-08-27
01-701-1023 | WEEK 2 | 2012-08-28 | 2012-09-01 | 2012-08-28 | 2012-09-01
01-703-1086 | BASELINE | 2012-09-02 | 2012-09-16 | 2012-09-02 | 2012-09-16
01-703-1086 | WEEK 2 | 2012-09-17 | 2012-12-04 | 2012-09-17 | 2012-12-04
01-703-1096 | BASELINE | 2013-01-25 | 2013-02-09 | 2013-01-25 | 2013-02-09
01-703-1096 | WEEK 2 | 2013-02-10 | 2013-03-16 | 2013-02-10 | 2013-03-16
01-707-1037 | BASELINE | 2013-12-20 | 2013-12-24 | 2013-12-20 | 2013-12-24

The example above imputes the start date to the first first day of the month and imputes the end date to the last day of the month.

Please see the Date and Time Imputation for additional examples on calculating and imputing analysis dates.

Next, the analysis study days can be derived:

    adex <-
      derive_vars_dy(adex,
        reference_date = TRTSDT,
        source_vars = exprs(ASTDT, AENDT)
      )

USUBJID | VISIT | ASTDT | ASTDY | AENDT | AENDY | TRTSDT
--- | --- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | 2014-01-02 | 1 | 2014-01-16 | 15 | 2014-01-02
01-701-1015 | WEEK 2 | 2014-01-17 | 16 | 2014-06-18 | 168 | 2014-01-02
01-701-1015 | WEEK 24 | 2014-06-19 | 169 | 2014-07-02 | 182 | 2014-01-02
01-701-1023 | BASELINE | 2012-08-05 | 1 | 2012-08-27 | 23 | 2012-08-05
01-701-1023 | WEEK 2 | 2012-08-28 | 24 | 2012-09-01 | 28 | 2012-08-05
01-703-1086 | BASELINE | 2012-09-02 | 1 | 2012-09-16 | 15 | 2012-09-02
01-703-1086 | WEEK 2 | 2012-09-17 | 16 | 2012-12-04 | 94 | 2012-09-02
01-703-1096 | BASELINE | 2013-01-25 | 1 | 2013-02-09 | 16 | 2013-01-25
01-703-1096 | WEEK 2 | 2013-02-10 | 17 | 2013-03-16 | 51 | 2013-01-25
01-707-1037 | BASELINE | 2013-12-20 | 1 | 2013-12-24 | 5 | 2013-12-20

## Compute duration for a record

To compute the duration of treatment or exposure for a record, the `derive_vars_duration()` function can be used.

    adex <- adex %>%
      derive_vars_duration(
        new_var = EXDURD,
        start_date = ASTDT,
        end_date = AENDT
      )

USUBJID | VISIT | ASTDT | ASTDY | AENDT | AENDY | EXDURD
--- | --- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | 2014-01-02 | 1 | 2014-01-16 | 15 | 15
01-701-1015 | WEEK 2 | 2014-01-17 | 16 | 2014-06-18 | 168 | 153
01-701-1015 | WEEK 24 | 2014-06-19 | 169 | 2014-07-02 | 182 | 14
01-701-1023 | BASELINE | 2012-08-05 | 1 | 2012-08-27 | 23 | 23
01-701-1023 | WEEK 2 | 2012-08-28 | 24 | 2012-09-01 | 28 | 5
01-703-1086 | BASELINE | 2012-09-02 | 1 | 2012-09-16 | 15 | 15
01-703-1086 | WEEK 2 | 2012-09-17 | 16 | 2012-12-04 | 94 | 79
01-703-1096 | BASELINE | 2013-01-25 | 1 | 2013-02-09 | 16 | 16
01-703-1096 | WEEK 2 | 2013-02-10 | 17 | 2013-03-16 | 51 | 35
01-707-1037 | BASELINE | 2013-12-20 | 1 | 2013-12-24 | 5 | 5

The units of the calculated duration can also be changed. In this example, the duration is output as years:

    adex <- adex %>%
      derive_vars_duration(
        new_var = EXDURDY,
        out_unit = "years",
        start_date = ASTDT,
        end_date = AENDT
      )

USUBJID | VISIT | ASTDT | AENDT | EXDURD | EXDURDY
--- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | 2014-01-02 | 2014-01-16 | 15 | 0.0410678
01-701-1015 | WEEK 2 | 2014-01-17 | 2014-06-18 | 153 | 0.4188912
01-701-1015 | WEEK 24 | 2014-06-19 | 2014-07-02 | 14 | 0.0383299
01-701-1023 | BASELINE | 2012-08-05 | 2012-08-27 | 23 | 0.0629706
01-701-1023 | WEEK 2 | 2012-08-28 | 2012-09-01 | 5 | 0.0136893
01-703-1086 | BASELINE | 2012-09-02 | 2012-09-16 | 15 | 0.0410678
01-703-1086 | WEEK 2 | 2012-09-17 | 2012-12-04 | 79 | 0.2162902
01-703-1096 | BASELINE | 2013-01-25 | 2013-02-09 | 16 | 0.0438056
01-703-1096 | WEEK 2 | 2013-02-10 | 2013-03-16 | 35 | 0.0958248
01-707-1037 | BASELINE | 2013-12-20 | 2013-12-24 | 5 | 0.0136893

Please refer to the `derive_vars_duration()` documentation for detailed information on the input parameters.

It may be necessary to calculate additional intermediate values. For example, the cumulative doses received and cumulative planned doses may be calculated as:

    adex <- adex %>%
      mutate(
        DOSEO = EXDOSE * EXDURD,
        PDOSEO = EXPLDOS * EXDURD
      )

USUBJID | EXDOSE | EXPLDOS | EXDURD | DOSEO | PDOSEO
--- | --- | --- | --- | --- | ---
01-701-1015 | 0 | 0 | 15 | 0 | 0
01-701-1015 | 0 | 0 | 153 | 0 | 0
01-701-1015 | 0 | 0 | 14 | 0 | 0
01-701-1023 | 0 | 0 | 23 | 0 | 0
01-701-1023 | 0 | 0 | 5 | 0 | 0
01-703-1086 | 54 | 54 | 15 | 810 | 810
01-703-1086 | 54 | 54 | 79 | 4266 | 4266
01-703-1096 | 0 | 0 | 16 | 0 | 0
01-703-1096 | 0 | 0 | 35 | 0 | 0
01-707-1037 | 54 | 54 | 5 | 270 | 270

It may be of additional interest to turn a single record containing dosing summary information into a set of multiple single records, each representing a single dose over the interval specified by the summary record. This is another approach to deriving a total dose parameter when `EXDOSFRQ != ONCE`.

The function `create_single_dose_dataset()` can be used to expand a record containing a start date, an end date, and a dosing frequency to a corresponding set of records each representing one dose (i.e. `EXDOSFRQ == "ONCE"`).

    single_dose <- adex %>%
      filter(USUBJID == "01-701-1015" & EXSTDY == 1) %>%
      create_single_dose_dataset(keep_source_vars = exprs(USUBJID, EXDOSE, EXPLDOS, EXDOSFRQ, ASTDT, AENDT))

USUBJID | EXDOSE | EXPLDOS | EXDOSFRQ | ASTDT | AENDT
--- | --- | --- | --- | --- | ---
01-701-1015 | 0 | 0 | ONCE | 2014-01-02 | 2014-01-02
01-701-1015 | 0 | 0 | ONCE | 2014-01-03 | 2014-01-03
01-701-1015 | 0 | 0 | ONCE | 2014-01-04 | 2014-01-04
01-701-1015 | 0 | 0 | ONCE | 2014-01-05 | 2014-01-05
01-701-1015 | 0 | 0 | ONCE | 2014-01-06 | 2014-01-06
01-701-1015 | 0 | 0 | ONCE | 2014-01-07 | 2014-01-07
01-701-1015 | 0 | 0 | ONCE | 2014-01-08 | 2014-01-08
01-701-1015 | 0 | 0 | ONCE | 2014-01-09 | 2014-01-09
01-701-1015 | 0 | 0 | ONCE | 2014-01-10 | 2014-01-10
01-701-1015 | 0 | 0 | ONCE | 2014-01-11 | 2014-01-11

## Create 1:1 mapping records

The first set of exposure records to create will be records mapped 1:1 to an existing collected exposure record in SDTM. For these records, the `AVAL` or `AVALC` would be calculated using columns that exist on the data and no summarizing of records would be necessary.

These records may be used for input into summary records or be used individually for summarization in outputs. Some examples may be exposure duration, dose administered, dose adjusted, etc. based on one exposure record in SDTM.

These records can be derived using simple `dplyr::mutate` assignments and then combined:

    adex_durd <- adex %>%
      mutate(
        PARAMCD = "DURD",
        AVAL = EXDURD
      )

    adex_dose <- adex %>%
      mutate(
        PARAMCD = "DOSE",
        AVAL = DOSEO
      )

    adex_pldos <- adex %>%
      mutate(
        PARAMCD = "PLDOSE",
        AVAL = PDOSEO
      )

    adex_adj <- adex %>%
      mutate(
        PARAMCD = "ADJ",
        AVALC = if_else(!is.na(EXADJ), "Y", NA_character_)
      )

    adex_adjae <- adex %>%
      mutate(
        PARAMCD = "ADJAE",
        AVALC = if_else(EXADJ == "ADVERSE EVENT", "Y", NA_character_)
      )

    adex <- bind_rows(
      adex_durd,
      adex_dose,
      adex_pldos,
      adex_adj,
      adex_adjae
    ) %>%
      mutate(PARCAT1 = "INDIVIDUAL")

    count(adex, PARAMCD)
    #> # A tibble: 5 × 2
    #>   PARAMCD     n
    #>   <chr>   <int>
    #> 1 ADJ        13
    #> 2 ADJAE      13
    #> 3 DOSE       13
    #> 4 DURD       13
    #> 5 PLDOSE     13

USUBJID | VISIT | ASTDT | AENDT | PARAMCD | AVAL | AVALC
--- | --- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | 2014-01-02 | 2014-01-16 | PLDOSE | 0 | NA
01-701-1015 | BASELINE | 2014-01-02 | 2014-01-16 | DURD | 15 | NA
01-701-1015 | BASELINE | 2014-01-02 | 2014-01-16 | DOSE | 0 | NA
01-701-1015 | BASELINE | 2014-01-02 | 2014-01-16 | ADJAE | NA | NA
01-701-1015 | BASELINE | 2014-01-02 | 2014-01-16 | ADJ | NA | NA
01-701-1015 | WEEK 2 | 2014-01-17 | 2014-06-18 | PLDOSE | 0 | NA
01-701-1015 | WEEK 2 | 2014-01-17 | 2014-06-18 | DURD | 153 | NA
01-701-1015 | WEEK 2 | 2014-01-17 | 2014-06-18 | DOSE | 0 | NA
01-701-1015 | WEEK 2 | 2014-01-17 | 2014-06-18 | ADJAE | NA | NA
01-701-1015 | WEEK 2 | 2014-01-17 | 2014-06-18 | ADJ | NA | NA

## Create Summary Records

Exposure is commonly analyzed by a timing interval (e.g. `APHASE`, `APERIOD`, `AVISIT`, etc.). For these types of calculations, the `derive_param_exposure()` function may be used. In addition to creating a summarized `AVAL`, the function will also compute minimum and maximum dates for the record.

For example, to calculate the total dose by subject and treatment,

    adex <- derive_param_exposure(
      adex,
      dataset_add = adex,
      by_vars = c(get_admiral_option("subject_keys"), adsl_vars),
      input_code = "DOSE",
      set_values_to = exprs(
        PARAMCD = "TDOSE",
        PARCAT1 = "OVERALL",
        AVAL = sum(AVAL, na.rm = TRUE)
      )
    )

USUBJID | VISIT | PARCAT1 | PARAMCD | AVAL | ASTDT | AENDT
--- | --- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | INDIVIDUAL | ADJ | NA | 2014-01-02 | 2014-01-16
01-701-1015 | WEEK 2 | INDIVIDUAL | ADJ | NA | 2014-01-17 | 2014-06-18
01-701-1015 | WEEK 24 | INDIVIDUAL | ADJ | NA | 2014-06-19 | 2014-07-02
01-701-1015 | BASELINE | INDIVIDUAL | ADJAE | NA | 2014-01-02 | 2014-01-16
01-701-1015 | WEEK 2 | INDIVIDUAL | ADJAE | NA | 2014-01-17 | 2014-06-18
01-701-1015 | WEEK 24 | INDIVIDUAL | ADJAE | NA | 2014-06-19 | 2014-07-02
01-701-1015 | BASELINE | INDIVIDUAL | DOSE | 0 | 2014-01-02 | 2014-01-16
01-701-1015 | WEEK 2 | INDIVIDUAL | DOSE | 0 | 2014-01-17 | 2014-06-18
01-701-1015 | WEEK 24 | INDIVIDUAL | DOSE | 0 | 2014-06-19 | 2014-07-02
01-701-1015 | BASELINE | INDIVIDUAL | DURD | 15 | 2014-01-02 | 2014-01-16

A record with `PARAMCD == "TDOSE"` is created with `PARCAT1` set to `"OVERALL"` using the records in `ADEX` where `PARAMCD == "DOSE"` by summing `AVAL`. In addition, the `ASTDT`, and `AENDT` are created as the minimum and maximum date/times associated with each `by_vars` grouping. Note that, in addition to `PARAMCD`, `PARCAT1`, `AVAL`, `ASTDT` and `AENDT`, only those variables specified in the `by_vars` argument will be populated in the new records.

Multiple parameters (records) may be created at one time using the `call_derivation()` function:

    adex <- adex %>%
      call_derivation(
        derivation = derive_param_exposure,
        variable_params = list(
          params(
            set_values_to = exprs(
              PARAMCD = "TDOSE",
              PARCAT1 = "OVERALL",
              AVAL = sum(AVAL, na.rm = TRUE)
            ),
            input_code = "DOSE"
          ),
          params(
            set_values_to = exprs(
              PARAMCD = "TPDOSE",
              PARCAT1 = "OVERALL",
              AVAL = sum(AVAL, na.rm = TRUE)
            ),
            input_code = "PLDOSE"
          ),
          params(
            set_values_to = exprs(
              PARAMCD = "TDURD",
              PARCAT1 = "OVERALL",
              AVAL = sum(AVAL, na.rm = TRUE)
            ),
            input_code = "DURD"
          ),
          params(
            set_values_to = exprs(
              PARAMCD = "TADJ",
              PARCAT1 = "OVERALL",
              AVALC = if_else(sum(!is.na(AVALC)) > 0, "Y", NA_character_)
            ),
            input_code = "ADJ"
          ),
          params(
            set_values_to = exprs(
              PARAMCD = "TADJAE",
              PARCAT1 = "OVERALL",
              AVALC = if_else(sum(!is.na(AVALC)) > 0, "Y", NA_character_)
            ),
            input_code = "ADJAE"
          )
        ),
        dataset_add = adex,
        by_vars = c(get_admiral_option("subject_keys"), adsl_vars)
      )

    count(adex, PARAMCD, PARCAT1)
    #> # A tibble: 10 × 3
    #>    PARAMCD PARCAT1        n
    #>    <chr>   <chr>      <int>
    #>  1 ADJ     INDIVIDUAL    13
    #>  2 ADJAE   INDIVIDUAL    13
    #>  3 DOSE    INDIVIDUAL    13
    #>  4 DURD    INDIVIDUAL    13
    #>  5 PLDOSE  INDIVIDUAL    13
    #>  6 TADJ    OVERALL        6
    #>  7 TADJAE  OVERALL        6
    #>  8 TDOSE   OVERALL        6
    #>  9 TDURD   OVERALL        6
    #> 10 TPDOSE  OVERALL        6

USUBJID | VISIT | PARCAT1 | PARAMCD | AVAL | AVALC | ASTDT | AENDT
--- | --- | --- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | INDIVIDUAL | ADJ | NA | NA | 2014-01-02 | 2014-01-16
01-701-1015 | WEEK 2 | INDIVIDUAL | ADJ | NA | NA | 2014-01-17 | 2014-06-18
01-701-1015 | WEEK 24 | INDIVIDUAL | ADJ | NA | NA | 2014-06-19 | 2014-07-02
01-701-1015 | BASELINE | INDIVIDUAL | ADJAE | NA | NA | 2014-01-02 | 2014-01-16
01-701-1015 | WEEK 2 | INDIVIDUAL | ADJAE | NA | NA | 2014-01-17 | 2014-06-18
01-701-1015 | WEEK 24 | INDIVIDUAL | ADJAE | NA | NA | 2014-06-19 | 2014-07-02
01-701-1015 | BASELINE | INDIVIDUAL | DOSE | 0 | NA | 2014-01-02 | 2014-01-16
01-701-1015 | WEEK 2 | INDIVIDUAL | DOSE | 0 | NA | 2014-01-17 | 2014-06-18
01-701-1015 | WEEK 24 | INDIVIDUAL | DOSE | 0 | NA | 2014-06-19 | 2014-07-02
01-701-1015 | BASELINE | INDIVIDUAL | DURD | 15 | NA | 2014-01-02 | 2014-01-16

Dose intensity can be calculated using the function `derive_param_doseint()`. The planned dose and administered dose are passed into the function and a new record is created with the dose intensity calculation. Again, only those variables specified in the `by_vars` argument will be populated in this new record.

    adex <- adex %>%
      derive_param_doseint(
        by_vars = c(get_admiral_option("subject_keys"), adsl_vars),
        set_values_to = exprs(PARAMCD = "TNDOSINT"),
        tadm_code = "TDOSE",
        tpadm_code = "TPDOSE"
      )

USUBJID | VISIT | EXSTDTC | EXENDTC | PARCAT1 | PARAMCD | AVAL | ASTDT | AENDT
--- | --- | --- | --- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | 2014-01-02 | 2014-01-16 | INDIVIDUAL | DURD | 15 | 2014-01-02 | 2014-01-16
01-701-1015 | WEEK 2 | 2014-01-17 | 2014-06-18 | INDIVIDUAL | DURD | 153 | 2014-01-17 | 2014-06-18
01-701-1015 | WEEK 24 | 2014-06-19 | 2014-07-02 | INDIVIDUAL | DURD | 14 | 2014-06-19 | 2014-07-02
01-701-1023 | BASELINE | 2012-08-05 | 2012-08-27 | INDIVIDUAL | DURD | 23 | 2012-08-05 | 2012-08-27
01-701-1023 | WEEK 2 | 2012-08-28 | 2012-09-01 | INDIVIDUAL | DURD | 5 | 2012-08-28 | 2012-09-01
01-703-1086 | BASELINE | 2012-09-02 | 2012-09-16 | INDIVIDUAL | DURD | 15 | 2012-09-02 | 2012-09-16
01-703-1086 | WEEK 2 | 2012-09-17 | 2012-12-04 | INDIVIDUAL | DURD | 79 | 2012-09-17 | 2012-12-04
01-703-1096 | BASELINE | 2013-01-25 | 2013-02-09 | INDIVIDUAL | DURD | 16 | 2013-01-25 | 2013-02-09
01-703-1096 | WEEK 2 | 2013-02-10 | 2013-03-16 | INDIVIDUAL | DURD | 35 | 2013-02-10 | 2013-03-16
01-707-1037 | BASELINE | 2013-12-20 | 2013-12-24 | INDIVIDUAL | DURD | 5 | 2013-12-20 | 2013-12-24

The default calculation for dose intensity is: Administered Doses / Planned Doses * 100.

Please see the `derive_param_doseint()` documentation to see how planned doses of 0 or `NA` are handled.

## Assign `PARAMCD`, `PARAMN`, etc. from Reference tables

To assign parameter level values such as `PARAM`, `PARAMN`, `PARCAT1`, etc., a lookup can be created to join to the source data.

For example, when creating `ADEX`, a lookup based on the ADaM `PARAMCD` value may be created:

PARAMCD | PARAM | PARAMN
--- | --- | ---
DURD | Study drug duration during constant dosing interval (days) | 1
DOSE | Dose administered during constant dosing interval (mg) | 2
PLDOSE | Planned dose during constant dosing interval (mg) | 3
ADJ | Dose adjusted during constant dosing interval | 4
ADJAE | Dose adjusted due to AE during constant dosing interval | 5
TDURD | Overall duration (days) | 6
TDOSE | Total dose administered (mg) | 7
TPDOSE | Total planned dose (mg) | 9
TADJ | Dose adjusted during study | 10
TADJAE | Dose adjusted during study due to AE | 11
TNDOSINT | Overall dose intensity (%) | 12

    adex <- derive_vars_merged(
      adex,
      dataset_add = param_lookup,
      by_vars = exprs(PARAMCD)
    )

    count(adex, PARAMCD, PARAM, PARAMN)
    #> # A tibble: 11 × 4
    #>    PARAMCD  PARAM                                                   PARAMN     n
    #>    <chr>    <chr>                                                    <dbl> <int>
    #>  1 ADJ      Dose adjusted during constant dosing interval                4    13
    #>  2 ADJAE    Dose adjusted  due to AE during constant dosing interv…      5    13
    #>  3 DOSE     Dose administered during constant dosing interval (mg)       2    13
    #>  4 DURD     Study drug duration during constant dosing interval (d…      1    13
    #>  5 PLDOSE   Planned dose during constant dosing interval (mg)            3    13
    #>  6 TADJ     Dose adjusted during study                                  10     6
    #>  7 TADJAE   Dose adjusted during study due to AE                        11     6
    #>  8 TDOSE    Total dose administered (mg)                                 7     6
    #>  9 TDURD    Overall duration (days)                                      6     6
    #> 10 TNDOSINT Overall dose intensity (%)                                  12     6
    #> 11 TPDOSE   Total planned dose (mg)                                      9     6

Please note, this is an example only and additional columns may be needed for the join depending on your lookup/metadata table.

## Derive Categorization Variables (`AVALCATy`)

We can use the `derive_vars_cat()` function to derive the categorization variables.

    avalcax_lookup <- exprs(
      ~PARAMCD,            ~condition,             ~AVALCAT1,
      "TDURD",             AVAL >= 90,          ">= 90 days",
      "TDURD", AVAL >= 30 & AVAL < 90, ">= 30 and < 90 days",
      "TDURD",              AVAL < 30,           "< 30 days",
      "TDOSE",            AVAL < 1000,           "< 1000 mg",
      "TDOSE",           AVAL >= 1000,          ">= 1000 mg",
      "TPDOSE",           AVAL < 1000,           "< 1000 mg",
      "TPDOSE",          AVAL >= 1000,          ">= 1000 mg"
    )

    adex <- adex %>%
      derive_vars_cat(
        definition = avalcax_lookup,
        by_vars = exprs(PARAMCD)
      )

USUBJID | VISIT | PARCAT1 | PARAMCD | AVAL | AVALCAT1
--- | --- | --- | --- | --- | ---
01-701-1015 | NA | OVERALL | TDOSE | 0 | < 1000 mg
01-701-1015 | NA | OVERALL | TPDOSE | 0 | < 1000 mg
01-701-1015 | NA | OVERALL | TDURD | 182 | >= 90 days
01-701-1015 | BASELINE | INDIVIDUAL | DURD | 15 | NA
01-701-1015 | BASELINE | INDIVIDUAL | DOSE | 0 | NA
01-701-1015 | BASELINE | INDIVIDUAL | PLDOSE | 0 | NA
01-701-1015 | BASELINE | INDIVIDUAL | ADJ | NA | NA
01-701-1015 | BASELINE | INDIVIDUAL | ADJAE | NA | NA
01-701-1015 | WEEK 2 | INDIVIDUAL | DURD | 153 | NA
01-701-1015 | WEEK 2 | INDIVIDUAL | DOSE | 0 | NA

## Assign `ASEQ`

The `{admiral}` function `derive_var_obs_number()` can be used to derive `ASEQ`. Note that creating `ASEQ` is not required for all ADaM datasets according to the ADaM IG, and this is just for demonstration purpose. An example call is:

    # Calculate ASEQ (Optional Variable)
    adex <- derive_var_obs_number(
      adex,
      new_var = ASEQ,
      by_vars = get_admiral_option("subject_keys"),
      order = exprs(PARCAT1, ASTDT, VISIT, VISITNUM, EXSEQ, PARAMN),
      check_type = "error"
    )

USUBJID | VISIT | PARCAT1 | PARAMCD | AVAL | ASTDT | ASEQ
--- | --- | --- | --- | --- | --- | ---
01-701-1015 | BASELINE | INDIVIDUAL | DURD | 15 | 2014-01-02 | 1
01-701-1015 | BASELINE | INDIVIDUAL | DOSE | 0 | 2014-01-02 | 2
01-701-1015 | BASELINE | INDIVIDUAL | PLDOSE | 0 | 2014-01-02 | 3
01-701-1015 | BASELINE | INDIVIDUAL | ADJ | NA | 2014-01-02 | 4
01-701-1015 | BASELINE | INDIVIDUAL | ADJAE | NA | 2014-01-02 | 5
01-701-1015 | WEEK 2 | INDIVIDUAL | DURD | 153 | 2014-01-17 | 6
01-701-1015 | WEEK 2 | INDIVIDUAL | DOSE | 0 | 2014-01-17 | 7
01-701-1015 | WEEK 2 | INDIVIDUAL | PLDOSE | 0 | 2014-01-17 | 8
01-701-1015 | WEEK 2 | INDIVIDUAL | ADJ | NA | 2014-01-17 | 9
01-701-1015 | WEEK 2 | INDIVIDUAL | ADJAE | NA | 2014-01-17 | 10

## Add the `ADSL` variables

If needed, the other `ADSL` variables can now be added:

    adex <- adex %>%
      derive_vars_merged(
        dataset_add = select(adsl, !!!negate_vars(adsl_vars)),
        by_vars = get_admiral_option("subject_keys")
      )

## Add Labels and Attributes

Note that attributes may not be preserved in some cases after processing with `{admiral}`. The recommended approach is to apply variable labels and other metadata as a final step in your data derivation process using packages like:

- metacore: establish a common foundation for the use of metadata within an R session.

- metatools: enable the use of metacore objects. Metatools can be used to build datasets or enhance columns in existing datasets as well as checking datasets against the metadata.

- xportr: functionality to associate all metadata information to a local R data frame, perform data set level validation checks and convert into a transport v5 file(xpt).

NOTE: Together with `{admiral}` these packages comprise an End to End pipeline under the umbrella of the pharmaverse. An example of applying metadata and performing associated checks can be found at the pharmaverse E2E example.

# Example Script

ADaM | Sourcing Command
--- | ---
`ADEX` | `use_ad_template("ADEX")`