The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Creating a Metabolic ADVS ADaM

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.

library(admiral)
library(admiralmetabolic)
library(pharmaversesdtm)
library(dplyr)

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.

Create PARAMCD, PARAM, PARAMN, PARCAT1 variables

The next step is to create and assign parameter level variables 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, "Anthropometric Measurement", 1,
  "WEIGHT", "WEIGHT", "Weight (kg)", 2, "Anthropometric Measurement", 1,
  "BMI", "BMI", "Body Mass Index(kg/m^2)", 3, "Anthropometric Measurement", 1,
  "HIPCIR", "HIPCIR", "Hip Circumference (cm)", 4, "Anthropometric Measurement", 1,
  "WSTCIR", "WSTCIR", "Waist Circumference (cm)", 5, "Anthropometric Measurement", 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)
)
USUBJID VSTESTCD PARAMCD PARAM PARCAT1 PARCAT1N
01-701-1015 BMI BMI Body Mass Index(kg/m^2) Anthropometric Measurement 1
01-701-1015 DIABP DIABP Diastolic Blood Pressure (mmHg) Vital Sign 2
01-701-1015 HEIGHT HEIGHT Height (cm) Anthropometric Measurement 1
01-701-1015 HIPCIR HIPCIR Hip Circumference (cm) Anthropometric Measurement 1
01-701-1015 PULSE PULSE Pulse Rate (beats/min) Vital Sign 2
01-701-1015 SYSBP SYSBP Systolic Blood Pressure (mmHg) Vital Sign 2
01-701-1015 TEMP TEMP Temperature (C) Vital Sign 2
01-701-1015 WEIGHT WEIGHT Weight (kg) Anthropometric Measurement 1
01-701-1015 WSTCIR WSTCIR Waist Circumference (cm) Anthropometric Measurement 1
01-701-1023 BMI BMI Body Mass Index(kg/m^2) Anthropometric Measurement 1

Derive Parameters for Metabolic indicators

In clinical trials focused on metabolic conditions, it’s common to derive additional parameters from the collected data. These derived parameters often provide valuable insights into the metabolic health of the subjects. In this vignette, we will explore how one could derive BMI and waist-hip ratio.

Derive BMI

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.

# Remove BMI collected in SDTM
advs <- advs %>% filter(VSTESTCD != "BMI" | is.na(VSTESTCD))

# Re-calculate 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 = "Anthropometric Measurement",
    PARCAT1N = 1
  ),
  get_unit_expr = VSSTRESU,
  constant_by_vars = exprs(USUBJID)
)
USUBJID VSTESTCD PARAMCD PARAM VISIT AVAL
01-701-1015 NA BMI Body Mass Index (kg/m^2) SCREENING 1 38.10500
01-701-1015 NA BMI Body Mass Index (kg/m^2) BASELINE 38.06228
01-701-1015 NA BMI Body Mass Index (kg/m^2) WEEK 2 38.53219
01-701-1015 NA BMI Body Mass Index (kg/m^2) WEEK 4 38.62617
01-701-1015 NA BMI Body Mass Index (kg/m^2) WEEK 6 38.67743
01-701-1015 NA BMI Body Mass Index (kg/m^2) WEEK 8 38.79277
01-701-1015 NA BMI Body Mass Index (kg/m^2) WEEK 12 38.95937
01-701-1015 NA BMI Body Mass Index (kg/m^2) WEEK 16 38.57918
01-701-1015 NA BMI Body Mass Index (kg/m^2) WEEK 20 39.03200
01-701-1015 NA BMI Body Mass Index (kg/m^2) WEEK 24 39.10889

Derive waist hip-ratio

Metabolic trials often include ratios between different anthropometric measurements. For this, {admiralmetabolic} provides several functions to quickly calculate various anthropometric ratios. For instance, the function derive_param_waisthip() can be used to derive the waist-hip ratio.

advs <- advs %>%
  derive_param_waisthip(
    by_vars = exprs(!!!get_admiral_option("subject_keys"), VISIT, VISITNUM),
    wstcir_code = "WSTCIR",
    hipcir_code = "HIPCIR",
    set_values_to = exprs(
      PARAMCD = "WAISTHIP",
      PARAM = "Waist to Hip Ratio"
    ),
    get_unit_expr = VSSTRESU
  )
USUBJID PARAMCD PARAM VISIT AVAL
01-701-1033 WAISTHIP Waist to Hip Ratio BASELINE 0.9727273
01-701-1034 WAISTHIP Waist to Hip Ratio BASELINE 0.9607352
01-701-1034 WAISTHIP Waist to Hip Ratio WEEK 16 0.9495652
01-701-1034 WAISTHIP Waist to Hip Ratio WEEK 20 0.9561404
01-701-1034 WAISTHIP Waist to Hip Ratio WEEK 24 0.9557522
01-701-1034 WAISTHIP Waist to Hip Ratio WEEK 26 0.9469027

Derive Variables for Metabolic indicators

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 (AVALCATy, BASECATy)

For deriving categorization variables (AVALCATy, BASECATy) {admiral} provides derive_vars_cat() (see documentation of the function for details).

avalcat_lookup <- exprs(
  ~PARAMCD, ~condition,                ~AVALCAT1,           ~AVALCA1N,
  "BMI",    AVAL < 18.5,               "Underweight",       1,
  "BMI",    AVAL >= 18.5 & AVAL < 25,  "Normal weight",     2,
  "BMI",    AVAL >= 25 & AVAL < 30,    "Overweight",        3,
  "BMI",    AVAL >= 30 & AVAL < 35,    "Obesity class I",   4,
  "BMI",    AVAL >= 35 & AVAL < 40,    "Obesity class II",  5,
  "BMI",    AVAL >= 40,                "Obesity class III", 6,
  "BMI",    is.na(AVAL),               NA_character_,       NA_integer_
)

# Derive BMI class (AVALCAT1, AVALCA1N)
advs <- advs %>%
  derive_vars_cat(
    definition = avalcat_lookup,
    by_vars = exprs(PARAMCD)
  )
USUBJID PARAMCD VISIT AVAL AVALCA1N AVALCAT1
01-701-1023 BMI SCREENING 1 38.55257 5 Obesity class II
01-701-1023 BMI BASELINE 38.52106 5 Obesity class II
01-701-1023 BMI WEEK 2 38.97272 5 Obesity class II
01-701-1023 BMI WEEK 4 39.28784 5 Obesity class II
01-701-1034 BMI SCREENING 1 40.69404 6 Obesity class III
01-701-1034 BMI BASELINE 40.43434 6 Obesity class III
01-701-1034 BMI WEEK 2 39.67406 5 Obesity class II
01-701-1034 BMI WEEK 4 39.48963 5 Obesity class II
01-701-1034 BMI WEEK 6 39.01163 5 Obesity class II
01-701-1034 BMI WEEK 8 38.81215 5 Obesity class II

Now we can use derive_var_base to derive the BASECATy/ BASECAyN variables.

advs <- advs %>%
  derive_var_base(
    by_vars = exprs(!!!get_admiral_option("subject_keys"), PARAMCD),
    source_var = AVALCAT1,
    new_var = BASECAT1
  ) %>%
  derive_var_base(
    by_vars = exprs(!!!get_admiral_option("subject_keys"), PARAMCD),
    source_var = AVALCA1N,
    new_var = BASECA1N
  )
USUBJID PARAMCD VISIT AVAL BASE ABLFL BASECA1N BASECAT1
01-701-1023 BMI SCREENING 1 38.55257 38.52106 NA 5 Obesity class II
01-701-1023 BMI BASELINE 38.52106 38.52106 Y 5 Obesity class II
01-701-1023 BMI WEEK 2 38.97272 38.52106 NA 5 Obesity class II
01-701-1023 BMI WEEK 4 39.28784 38.52106 NA 5 Obesity class II
01-701-1034 BMI SCREENING 1 40.69404 40.43434 NA 6 Obesity class III
01-701-1034 BMI BASELINE 40.43434 40.43434 Y 6 Obesity class III
01-701-1034 BMI WEEK 2 39.67406 40.43434 NA 6 Obesity class III
01-701-1034 BMI WEEK 4 39.48963 40.43434 NA 6 Obesity class III
01-701-1034 BMI WEEK 6 39.01163 40.43434 NA 6 Obesity class III
01-701-1034 BMI WEEK 8 38.81215 40.43434 NA 6 Obesity class III

Derive Criterion Variables (CRITy, CRITyFL, CRITyFN)

For deriving criterion variables (CRITy, CRITyFL, CRITyFN) {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 and in this case the higher order function restrict_derivation() can be useful. 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 %>%
  restrict_derivation(
    derivation = derive_vars_crit_flag,
    args = params(
      condition = PCHG <= -5 & PARAMCD == "WEIGHT",
      description = "Achievement of >= 5% weight reduction from baseline",
      crit_nr = 1,
      values_yn = TRUE,
      create_numeric_flag = FALSE
    ),
    filter = VISITNUM > 0 & PARAMCD == "WEIGHT"
  ) %>%
  restrict_derivation(
    derivation = derive_vars_crit_flag,
    args = params(
      condition = PCHG <= -10 & PARAMCD == "WEIGHT",
      description = "Achievement of >= 10% weight reduction from baseline",
      crit_nr = 2,
      values_yn = TRUE,
      create_numeric_flag = FALSE
    ),
    filter = VISITNUM > 0 & PARAMCD == "WEIGHT"
  )
USUBJID PARAMCD PCHG CRIT1 CRIT1FL CRIT2 CRIT2FL VISIT VISITNUM
01-701-1033 WEIGHT 0.000000 Achievement of >= 5% weight reduction from baseline N Achievement of >= 10% weight reduction from baseline N BASELINE 3
01-701-1034 WEIGHT 0.000000 Achievement of >= 5% weight reduction from baseline N Achievement of >= 10% weight reduction from baseline N BASELINE 3
01-701-1034 WEIGHT -9.317695 Achievement of >= 5% weight reduction from baseline Y Achievement of >= 10% weight reduction from baseline N WEEK 16 10
01-701-1034 WEIGHT -9.755189 Achievement of >= 5% weight reduction from baseline Y Achievement of >= 10% weight reduction from baseline N WEEK 20 11
01-701-1034 WEIGHT -11.700642 Achievement of >= 5% weight reduction from baseline Y Achievement of >= 10% weight reduction from baseline Y WEEK 24 12
01-701-1034 WEIGHT -12.398771 Achievement of >= 5% weight reduction from baseline Y Achievement of >= 10% weight reduction from baseline Y WEEK 26 13

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

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.