Skip to contents

Introduction

This article describes creating a vital signs ADaM for metabolic clinical trials.

We advise you first consult the admiral Creating a BDS Finding ADaM vignette. The programming workflow around creating the general set-up of an ADVS using admiral functions is the same. In this vignette, we focus on the most common endpoints and their derivations mainly found in metabolic trials to avoid repeating information and maintaining the same content in two places. As such, the code in this vignette is not completely executable; we recommend consulting the ADVS template script to view the full workflow.

Required Packages

The examples of this vignette require the following packages.

Programming Workflow

Read in Data

To start, all data frames needed for the creation of ADVS should be loaded into the global environment. Reading data will usually be a company specific process, however, for the purpose of this vignette, we will use example data from pharmaversesdtm and admiral. We will utilize DM, VS and ADSL for the basis of ADVS.

dm_metabolic <- admiralmetabolic::dm_metabolic
vs_metabolic <- admiralmetabolic::vs_metabolic
admiral_adsl <- admiral::admiral_adsl

dm <- convert_blanks_to_na(dm_metabolic)
vs <- convert_blanks_to_na(vs_metabolic)
admiral_adsl <- convert_blanks_to_na(admiral_adsl)

Within this vignette, DM is used as the basis for ADSL:

# Retrieve required variables from admiral ADSL for this vignette that are not present in DM dataset
adsl <- dm %>%
  select(-DOMAIN) %>%
  mutate(TRT01P = ARM, TRT01A = ACTARM) %>%
  left_join(admiral_adsl %>% select(USUBJID, TRTSDT, TRTEDT), by = "USUBJID")

The following steps are to merge ADSL variables with the source data and derive the usual ADVS analysis variables. Note that only the sections required for this vignette are covered in the following steps. To get a detailed guidance on all the steps, refer the admiral Creating a BDS Finding ADaM vignette.

Assign PARAMCD, PARAM, PARAMN, PARCAT1

The next step is to assign parameter level values such as PARAMCD, PARAM, PARAMN, PARCAT1, etc. For this, a lookup can be created based on the SDTM --TESTCD value to join to the source data. One key addition in metabolic trials are vital sign parameters associated to body measurements, such as BMI, HIPCIR, and WSTCIR.

param_lookup <- tribble(
  ~VSTESTCD, ~PARAMCD, ~PARAM, ~PARAMN, ~PARCAT1, ~PARCAT1N,
  "HEIGHT", "HEIGHT", "Height (cm)", 1, "Subject Characteristic", 1,
  "WEIGHT", "WEIGHT", "Weight (kg)", 2, "Subject Characteristic", 1,
  "BMI", "BMI", "Body Mass Index(kg/m^2)", 3, "Subject Characteristic", 1,
  "HIPCIR", "HIPCIR", "Hip Circumference (cm)", 4, "Subject Characteristic", 1,
  "WSTCIR", "WSTCIR", "Waist Circumference (cm)", 5, "Subject Characteristic", 1,
  "DIABP", "DIABP", "Diastolic Blood Pressure (mmHg)", 6, "Vital Sign", 2,
  "PULSE", "PULSE", "Pulse Rate (beats/min)", 7, "Vital Sign", 2,
  "SYSBP", "SYSBP", "Systolic Blood Pressure (mmHg)", 8, "Vital Sign", 2,
  "TEMP", "TEMP", "Temperature (C)", 9, "Vital Sign", 2
)

This lookup may now be joined to the source data and this is how the parameters will look like:

advs <- derive_vars_merged_lookup(
  advs,
  dataset_add = param_lookup,
  new_vars = exprs(PARAMCD, PARAM, PARAMN, PARCAT1, PARCAT1N),
  by_vars = exprs(VSTESTCD)
)

Derive Additional Parameters (e.g. BMI for ADVS)

In metabolic trials, BMI is often calculated at source. But while creating the ADVS dataset, we re-derive BMI from the collected height and weight values. This is done to ensure that the BMI is calculated consistently across all subjects and visits.

In this step, we create parameter Body Mass Index (BMI) for the ADVS domain using the derive_param_bmi() function. Note that only variables specified in the by_vars argument will be populated in the newly created records. Also note that if height is collected only once for a subject use constant_by_vars to specify the function to merge by the subject-level variable - otherwise BMI is only calculated for visits where both are collected.

# Removing BMI collected at source from the dataset
advs <- advs %>% filter(!VSTESTCD == "BMI")

advs <- derive_param_bmi(
  advs,
  by_vars = c(
    get_admiral_option("subject_keys"),
    exprs(!!!adsl_vars, VISIT, VISITNUM, ADT, ADY, VSTPT, VSTPTNUM)
  ),
  set_values_to = exprs(
    PARAMCD = "BMI",
    PARAM = "Body Mass Index (kg/m^2)",
    PARAMN = 3,
    PARCAT1 = "Subject Characteristic",
    PARCAT1N = 1
  ),
  get_unit_expr = VSSTRESU,
  filter = VSSTAT != "NOT DONE" | is.na(VSSTAT),
  constant_by_vars = exprs(USUBJID)
)

Common Metabolic Endpoints

In the following sections, we will explore some of the most common endpoints typically observed in metabolic trials.

One such endpoint is the improvement in weight category from baseline to the end of treatment, which is often assessed using Body Mass Index (BMI). To capture this, we will derive variables such as AVALCATy and BASECATy, as detailed in the subsequent section.

Additionally, the achievement of weight reduction thresholds, such as ≥ 5%, ≥ 10%, or ≥ 15% from baseline to end of treatment or at a certain visit, is a common endpoint in metabolic trials. To accommodate these criteria, we will derive relevant criterion variables such as CRITy, CRITyFL, and CRITyFLN, with the necessary functions provided by admiral outlined below.

Derive Categorization Variables (AVALCATx, BASECATx)

admiral does not currently have a generic function to aid in assigning AVALCATy/ AVALCAvN and BASECATy/ BASECAvN values. Below is a simple example of how these values may be assigned:

avalcat_lookup <- tibble::tribble(
  ~PARAMCD, ~AVALCA1N, ~AVALCAT1,
  "BMI",    1,         "Underweight",
  "BMI",    2,         "Normal weight",
  "BMI",    3,         "Overweight",
  "BMI",    4,         "Obesity class I",
  "BMI",    5,         "Obesity class II",
  "BMI",    6,         "Obesity class III",
  "BMI",    NA,        NA_character_
)

format_avalcat1n <- function(param, aval) {
  case_when(
    param == "BMI" & aval < 18.5 ~ 1,
    param == "BMI" & aval >= 18.5 & aval < 25 ~ 2,
    param == "BMI" & aval >= 25 & aval < 30 ~ 3,
    param == "BMI" & aval >= 30 & aval < 35 ~ 4,
    param == "BMI" & aval >= 35 & aval < 40 ~ 5,
    param == "BMI" & aval >= 40 ~ 6,
    TRUE ~ NA_real_
  )
}

advs <- advs %>%
  mutate(AVALCA1N = format_avalcat1n(param = PARAMCD, aval = AVAL)) %>%
  derive_vars_merged(
    avalcat_lookup,
    by = exprs(PARAMCD, AVALCA1N)
  )

In a similar way, we will create BASECATy/ BASECAvN variables.

basecat_lookup <- tibble::tribble(
  ~PARAMCD, ~BASECA1N, ~BASECAT1,
  "BMI",    1,         "Underweight",
  "BMI",    2,         "Normal weight",
  "BMI",    3,         "Overweight",
  "BMI",    4,         "Obesity class I",
  "BMI",    5,         "Obesity class II",
  "BMI",    6,         "Obesity class III",
  "BMI",    NA,        NA_character_
)

format_basecat1n <- function(param, base) {
  case_when(
    param == "BMI" & base < 18.5 ~ 1,
    param == "BMI" & base >= 18.5 & base < 25 ~ 2,
    param == "BMI" & base >= 25 & base < 30 ~ 3,
    param == "BMI" & base >= 30 & base < 35 ~ 4,
    param == "BMI" & base >= 35 & base < 40 ~ 5,
    param == "BMI" & base >= 40 ~ 6,
    TRUE ~ NA_real_
  )
}
advs <- advs %>%
  mutate(BASECA1N = format_basecat1n(param = PARAMCD, base = BASE)) %>%
  derive_vars_merged(
    basecat_lookup,
    by = exprs(PARAMCD, BASECA1N)
  )

Derive Criterion Variables (CRITy, CRITyFL, CRITyFLN)

For deriving criterion variables (CRITy, CRITyFL, CRITyFLN) admiral provides derive_vars_crit_flag(). It ensures that they are derived in an ADaM-compliant way (see documentation of the function for details).

In most cases the criterion depends on the parameter. In the following example, the criterion flags for weight based on percentage change in weight reduction from baseline is derived. Additional criterion flags can be added as needed.

advs <- advs %>%
  derive_vars_crit_flag(
    condition = PCHG <= -5 & PARAMCD == "WEIGHT",
    description = "Achievement of ≥ 5% weight reduction from baseline",
    crit_nr = 1,
    values_yn = TRUE,
    create_numeric_flag = FALSE
  ) %>%
  derive_vars_crit_flag(
    condition = PCHG <= -10 & PARAMCD == "WEIGHT",
    description = "Achievement of ≥ 10% weight reduction from baseline",
    crit_nr = 2,
    values_yn = TRUE,
    create_numeric_flag = FALSE
  )

Remaining ADVS Set-up

The admiral Creating a BDS Finding ADaM vignette covers all the steps that are not shown here, such as merging the parameter-level values, timing variables, and analysis flags.

Example Scripts

ADaM Sample Code
ADVS ad_advs.R