Hy's Law Implementation

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

library(admiraldev)

Introduction

During the drug development process, clinical trials are often required to assess for the potential that the experimental drug can cause severe liver injury, known as a drug induced liver injury (DILI). There are multiple criteria that need to be evaluated to determine and classify a DILI "Event". Hy's Law, a common rule of thumb for a DILI Event , is usually comprised of three parts:

Required Packages

The examples of this vignette require the following packages.

library(admiral)
library(dplyr, warn.conflicts = FALSE)

Programming Workflow

Read in Data {#readdata}

We assume that an ADLB dataset is available [^1].

[^1]: In the walk through below we will use the ADLB dataset created from the call use_ad_template("adlb"). Due to the size of the dataset, we only included the following USUBJIDs:

* `01-701-1015`, `01-701-1023`, `01-701-1028`, `01-701-1033`, `01-701-1034`, `01-701-1047`, `01-701-1097`, `01-705-1186`, `01-705-1292`, `01-705-1310`, `01-708-1286`.

First we read in the ADLB parameters required for the Hy's Law parameters:

data(admiral_adlb)
adlb <- admiral_adlb %>%
  filter(PARAMCD %in% c("AST", "ALT", "BILI") & is.na(DTYPE))
head(adlb) %>%
  dataset_vignette()

Flagging Elevated Values (CRITy, CRITyFL) {#columns}

A standard convention of ADLBHY datasets, are various CRITy and CRITyFL columns to describe the conditions necessary to reach that particular criterion of Hy's Law and the actual flag itself to indicate whether or not the condition was reached.

Using mutate(), call_derivation() and derive_var_merged_exist_flag(), we can create these columns that indicate the the 3-fold or greater than upper limit of normal of ALT/AST and the 2-fold or greater than upper limit of normal of BILI.

To increase visibility and for simplicity, we will retain only columns that are relevant to a Hy's Law analysis for now.

adlb_annotated <- adlb %>%
  mutate(
    CRIT1 = case_when(
      PARAMCD == "AST" ~ "AST >=3xULN",
      PARAMCD == "ALT" ~ "ALT >=3xULN",
      PARAMCD == "BILI" ~ "BILI >=2xULN"
    ),
    CRIT1FL = if_else(
      (AVAL / ANRHI >= 3 & PARAMCD %in% c("AST", "ALT")) |
        (AVAL / ANRHI >= 2 & PARAMCD == "BILI"),
      "Y",
      NA_character_
    )
  ) %>%
  select(STUDYID, USUBJID, TRT01A, PARAMCD, LBSEQ, ADT, AVISIT, ADY, AVAL, ANRHI, CRIT1, CRIT1FL)
dataset_vignette(adlb_annotated)

Subsetting by LBTESTCD and Joining by Potential Events {#joins}

If an elevated ALT/AST event reaches the threshold for Hy's Law, we need to search for any elevated BILI events within a certain time-window, usually up to 14 days after the elevated ALT/AST event (this window may vary by organization). By,

1) Splitting our dataset into its ALT/AST and BILI subsets, respectively, and 2) Joining these two datasets using derive_vars_joined() while using the filter_join argument to only join together the relevant flagged BILI records that have a corresponding flagged ALT/AST record (prior up to 14 days but may vary for trial/organization) that would indicate a potential Hy's Law event,

the resulting dataset is helpful for deriving additional parameters. The dataset may also prove useful for a listing where you have to display the two lab-records in one row to showcase the potential event.

altast_records <- adlb_annotated %>%
  filter(PARAMCD %in% c("AST", "ALT"))

bili_records <- adlb_annotated %>%
  filter(PARAMCD %in% c("BILI"))

hylaw_records <- derive_vars_joined(
  dataset = altast_records,
  dataset_add = bili_records,
  by_vars = exprs(STUDYID, USUBJID),
  order = exprs(ADY),
  filter_join = 0 <= ADT.join - ADT & ADT.join - ADT <= 14 & CRIT1FL == "Y" & CRIT1FL.join == "Y",
  new_vars = exprs(BILI_DT = ADT, BILI_CRITFL = CRIT1FL),
  mode = "first"
)
hylaw_records %>%
  arrange(desc(BILI_CRITFL), desc(CRIT1FL)) %>%
  dataset_vignette()

How to Create New Parameters and Rows {#newparams}

Using derive_param_exist_flag() you can create a variety of parameters for your final dataset with AVAL = 1/0 for your specific Hy's Law analysis. Below is an example of how to indicate a potential Hy's Law event, with PARAMCD set as "HYSLAW" and PARAM set to "ALT/AST >= 3xULN and BILI >= 2xULN" for each patient using the flags from the prior dataset. This method allows for flexibility as well, if parameters for each visit was desired, you would add AVISIT and ADT to the select() and by_vars lines as denoted from the following code.

Additional modifications can be made such as:

hylaw_records_pts_visits <- hylaw_records %>%
  select(STUDYID, USUBJID, TRT01A) %>% # add AVISIT, ADT for by visit
  distinct()

hylaw_records_fls <- hylaw_records %>%
  select(STUDYID, USUBJID, TRT01A, CRIT1FL, BILI_CRITFL) %>% # add AVISIT, ADT for by visit
  distinct()

hylaw_params <- derive_param_exist_flag(
  dataset_ref = hylaw_records_pts_visits,
  dataset_add = hylaw_records_fls,
  condition = CRIT1FL == "Y" & BILI_CRITFL == "Y",
  false_value = "N",
  missing_value = "N",
  by_vars = exprs(STUDYID, USUBJID, TRT01A), # add AVISIT, ADT for by visit
  set_values_to = exprs(
    PARAMCD = "HYSLAW",
    PARAM = "ALT/AST >= 3xULN and BILI >= 2xULN",
    AVAL = yn_to_numeric(AVALC)
  )
)
hylaw_params %>%
  arrange(desc(AVAL)) %>%
  dataset_vignette()

The last step would be binding these rows back to whatever previous dataset is appropriate based on your data specifications, in this case, it would be best suited to bind back to our adlb_annotated object.

Conclusion {#conclusion}

adlbhy <- adlb_annotated %>%
  bind_rows(hylaw_params)
dataset_vignette(adlbhy)

Here we demonstrated what is the base-case that may be asked of as a trial programmer. The reality is that Hy's Law and assessing potential DILI events can get rather complex quite quickly. Differences in assessment across organizations and specific trials might require modifications, which may include:

We hope by demonstrating the flexibility of admiral functions and using a general workflow to create the necessary parameters for an ADLBHY, that creating this final dataset becomes simplified and easily scalable. Ideally, this is ready for your organization's standard macros or previous code for TLFs and outputs as well. This is our first attempt at breaking down and summarizing this topic. We welcome feedback and ideas to improve this guide!

Example Script

ADaM | Sample Code -------| -------------- ADLBHY | ad_adlbhy.R{target="_blank"}



Try the admiral package in your browser

Any scripts or data that you put into this service are public.

admiral documentation built on Oct. 19, 2023, 1:08 a.m.