Skip to contents

[Stable]

Primary analysis variable .var indicates the toxicity grade (factor), and additional analysis variables are id (character or factor), param (factor) and grade_dir (factor). The pre-processing steps are crucial when using this function. For a certain direction (e.g. high or low) this function counts patients in the denominator as number of patients with at least one valid measurement during treatment, and patients in the numerator as follows:

  • 1 to 4: Numerator is number of patients with worst grades 1-4 respectively;

  • Any: Numerator is number of patients with at least one abnormality, which means grade is different from 0.

Usage

s_count_abnormal_by_worst_grade(
  df,
  .var = "GRADE_ANL",
  .spl_context,
  variables = list(id = "USUBJID", param = "PARAM", grade_dir = "GRADE_DIR")
)

a_count_abnormal_by_worst_grade(
  df,
  .var = "GRADE_ANL",
  .spl_context,
  variables = list(id = "USUBJID", param = "PARAM", grade_dir = "GRADE_DIR")
)

count_abnormal_by_worst_grade(
  lyt,
  var,
  ...,
  .stats = NULL,
  .formats = NULL,
  .labels = NULL,
  .indent_mods = NULL
)

Arguments

df

(data frame)
data set containing all analysis variables.

.var, var

(string)
single variable name that is passed by rtables when requested by a statistics function.

.spl_context

(data frame)
gives information about ancestor split states that is passed by rtables.

variables

(named list of string)
list of additional analysis variables.

lyt

(layout)
input layout where analyses will be added to.

...

additional arguments for the lower level functions.

.stats

(character)
statistics to select for the table.

.formats

(named character or list)
formats for the statistics.

.labels

(named character)
labels for the statistics (without indent).

.indent_mods

(named integer)
indent modifiers for the labels.

Value

s_count_abnormal_by_worst_grade() the single statistic count_fraction with grade 1 to 4 and "Any" results.

a_count_abnormal_by_worst_grade() returns the corresponding list with formatted rtables::CellValue().

Details

The pre-processing steps are crucial when using this function. From the standard lab grade variable ATOXGR, derive the following two variables:

  • A grade direction variable (e.g. GRADE_DIR) is required in order to obtain the correct denominators when building the layout as it is used to define row splitting.

  • A toxicity grade variable (e.g. GRADE_ANL) where all negative values from ATOXGR are replaced by their absolute values.

  • Prior to tabulation, df must filtered to include only post-baseline records with worst grade flags.

Functions

  • s_count_abnormal_by_worst_grade(): Statistics function which counts patients with worst grade, consisting of counts and percentages of patients with worst grade 1 to 4, and Any non-zero grade.

  • a_count_abnormal_by_worst_grade(): Formatted Analysis function which can be further customized by calling rtables::make_afun() on it. It is used as afun in rtables::analyze().

  • count_abnormal_by_worst_grade(): Layout creating function which can be used for creating tables, which can take statistics function arguments and additional format arguments (see below).

Examples

library(scda)
#> 
library(dplyr)
library(forcats)

adlb <- synthetic_cdisc_data("latest")$adlb

# Data is modified in order to have some parameters with grades only in one direction
# and simulate the real data.
adlb$ATOXGR[adlb$PARAMCD == "ALT" & adlb$ATOXGR %in% c("1", "2", "3", "4")] <- "-1"
adlb$ANRIND[adlb$PARAMCD == "ALT" & adlb$ANRIND == "HIGH"] <- "LOW"
adlb$WGRHIFL[adlb$PARAMCD == "ALT"] <- ""

adlb$ATOXGR[adlb$PARAMCD == "IGA" & adlb$ATOXGR %in% c("-1", "-2", "-3", "-4")] <- "1"
adlb$ANRIND[adlb$PARAMCD == "IGA" & adlb$ANRIND == "LOW"] <- "HIGH"
adlb$WGRLOFL[adlb$PARAMCD == "IGA"] <- ""

# Here starts the real pre-processing.
adlb_f <- adlb %>%
  filter(!AVISIT %in% c("SCREENING", "BASELINE")) %>%
  mutate(
    GRADE_DIR = factor(case_when(
      ATOXGR %in% c("-1", "-2", "-3", "-4") ~ "LOW",
      ATOXGR == "0" ~ "ZERO",
      ATOXGR %in% c("1", "2", "3", "4") ~ "HIGH"
    ),
    levels = c("LOW", "ZERO", "HIGH")
    ),
    GRADE_ANL = fct_relevel(
      fct_recode(ATOXGR, `1` = "-1", `2` = "-2", `3` = "-3", `4` = "-4"),
      c("0", "1", "2", "3", "4")
    )
  ) %>%
  filter(WGRLOFL == "Y" | WGRHIFL == "Y") %>%
  droplevels()

adlb_f_alt <- adlb_f %>%
  filter(PARAMCD == "ALT") %>%
  droplevels()
full_parent_df <- list(adlb_f_alt, "not_needed")
cur_col_subset <- list(rep(TRUE, nrow(adlb_f_alt)), "not_needed")

# This mimics a split structure on PARAM and GRADE_DIR for a total column
spl_context <- data.frame(
  split = c("PARAM", "GRADE_DIR"),
  full_parent_df = I(full_parent_df),
  cur_col_subset = I(cur_col_subset)
)

# Internal function - s_count_abnormal_by_worst_grade
if (FALSE) {
s_count_abnormal_by_worst_grade(
  df = adlb_f_alt,
  .spl_context = spl_context,
  .var = "GRADE_ANL"
)
}

# Internal function - a_count_abnormal_by_worst_grade
if (FALSE) {
# Use the Formatted Analysis function for `analyze()`. We need to ungroup `count_fraction` first
# so that the `rtables` formatting function `format_count_fraction()` can be applied correctly.
afun <- make_afun(a_count_abnormal_by_worst_grade, .ungroup_stats = "count_fraction")
afun(df = adlb_f_alt, .spl_context = spl_context)
}

# Map excludes records without abnormal grade since they should not be displayed
# in the table.
map <- unique(adlb_f[adlb_f$GRADE_DIR != "ZERO", c("PARAM", "GRADE_DIR", "GRADE_ANL")]) %>%
  lapply(as.character) %>%
  as.data.frame() %>%
  arrange(PARAM, desc(GRADE_DIR), GRADE_ANL)

basic_table() %>%
  split_cols_by("ARMCD") %>%
  split_rows_by("PARAM") %>%
  split_rows_by("GRADE_DIR", split_fun = trim_levels_to_map(map)) %>%
  count_abnormal_by_worst_grade(
    var = "GRADE_ANL",
    variables = list(id = "USUBJID", param = "PARAM", grade_dir = "GRADE_DIR")
  ) %>%
  build_table(df = adlb_f)
#>                                          ARM A        ARM B        ARM C   
#> ———————————————————————————————————————————————————————————————————————————
#> Alanine Aminotransferase Measurement                                       
#>   LOW                                                                      
#>     1                                  14 (10.4%)   15 (11.2%)   10 (7.6%) 
#>     2                                  13 (9.7%)    18 (13.4%)   11 (8.3%) 
#>     3                                  20 (14.9%)    12 (9%)     10 (7.6%) 
#>     4                                   7 (5.2%)      8 (6%)     10 (7.6%) 
#>     Any                                54 (40.3%)   53 (39.6%)   41 (31.1%)
#> C-Reactive Protein Measurement                                             
#>   LOW                                                                      
#>     1                                  16 (11.9%)   19 (14.2%)   15 (11.4%)
#>     2                                  21 (15.7%)   13 (9.7%)    16 (12.1%)
#>     3                                   12 (9%)      9 (6.7%)    18 (13.6%)
#>     4                                  11 (8.2%)     7 (5.2%)     5 (3.8%) 
#>     Any                                60 (44.8%)   48 (35.8%)   54 (40.9%)
#>   HIGH                                                                     
#>     1                                  17 (12.7%)   15 (11.2%)    9 (6.8%) 
#>     2                                  15 (11.2%)   16 (11.9%)   13 (9.8%) 
#>     3                                  16 (11.9%)    12 (9%)     14 (10.6%)
#>     4                                   12 (9%)      12 (9%)     10 (7.6%) 
#>     Any                                60 (44.8%)    55 (41%)    46 (34.8%)
#> Immunoglobulin A Measurement                                               
#>   HIGH                                                                     
#>     1                                  25 (18.7%)   14 (10.4%)   13 (9.8%) 
#>     2                                  14 (10.4%)   20 (14.9%)   16 (12.1%)
#>     3                                   12 (9%)     13 (9.7%)    17 (12.9%)
#>     4                                  11 (8.2%)    13 (9.7%)      4 (3%)  
#>     Any                                62 (46.3%)   60 (44.8%)   50 (37.9%)