---
title: LBT14
subtitle: Laboratory Test Results Shift Table -- Highest NCI CTCAE Grade Post-Baseline by Baseline NCI CTCAE Grade
---
------------------------------------------------------------------------
{{< include ../../_utils/envir_hook.qmd >}}
```{r setup, echo = FALSE, warning = FALSE, message = FALSE}
library(dplyr)
library(tern)
adsl <- random.cdisc.data::cadsl
adlb <- random.cdisc.data::cadlb
adsl <- df_explicit_na(adsl)
adlb <- df_explicit_na(adlb)
# Please note that in real clinical data, population flag like SAFFL, and parameter category like PARCAT2 needs to be
# selected properly.
adsl_f <- adsl %>% filter(SAFFL == "Y")
adlb <- adlb %>% filter(SAFFL == "Y")
```
```{r include = FALSE}
webr_code_labels <- c("setup")
```
{{< include ../../_utils/webr_no_include.qmd >}}
## Output
:::::::: panel-tabset
## Standard Table (High)
Note that the worst laboratory flag (below `WGRHIFL` ) must be selected appropriately in the pre-processing step. New grouping variables `ATOXGR_GP` (post-baseline) and `BTOXGR_GP` (baseline) are created to display the correct output.
::: {.panel-tabset .nav-justified group="webr"}
## {{< fa regular file-lines sm fw >}} Preview
```{r variant1, test = list(result_v1 = "result")}
adlb_f <- adlb %>% filter(WGRHIFL == "Y")
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- h_adsl_adlb_merge_using_worst_flag(adsl_f, adlb_f, worst_flag = c("WGRHIFL" = "Y"))
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
mutate(
ATOXGR_GP = factor(case_when(
ATOXGR %in% c(0, -1, -2, -3, -4) ~ "Not High",
ATOXGR == 1 ~ "1",
ATOXGR == 2 ~ "2",
ATOXGR == 3 ~ "3",
ATOXGR == 4 ~ "4",
ATOXGR == "<Missing>" ~ "Missing"
), levels = c("Not High", "1", "2", "3", "4", "Missing"))
) %>%
mutate(
BTOXGR_GP = factor(case_when(
BTOXGR %in% c(0, -1, -2, -3, -4) ~ "Not High",
BTOXGR == 1 ~ "1",
BTOXGR == 2 ~ "2",
BTOXGR == 3 ~ "3",
BTOXGR == 4 ~ "4",
BTOXGR == "<Missing>" ~ "Missing"
), levels = c("Not High", "1", "2", "3", "4", "Missing"))
)
result <- basic_table(show_colcounts = TRUE) %>%
split_cols_by("ACTARM") %>%
split_rows_by(
"PARAM",
split_fun = drop_split_levels,
label_pos = "topleft",
split_label = "Parameter"
) %>%
split_rows_by(
"BTOXGR_GP",
label_pos = "topleft",
split_label = " Baseline NCI-CTCAE Grade",
indent_mod = 2L
) %>%
summarize_num_patients(var = "USUBJID", .stats = c("unique_count"), unique_count_suffix = FALSE) %>%
count_occurrences_by_grade("ATOXGR_GP", denom = "n", drop = FALSE, .indent_mods = 3L) %>%
append_topleft(" Post-baseline NCI-CTCAE Grade") %>%
build_table(df = adlb_out, alt_counts_df = adsl_f) %>%
prune_table()
result
```
```{r include = FALSE}
webr_code_labels <- c("variant1")
```
{{< include ../../_utils/webr.qmd >}}
:::
## Standard Table (Low)
Note that the worst laboratory flag (below `WGRLOFL` ) must be selected appropriately in the pre-processing step. New grouping variables `ATOXGR_GP` (post-baseline) and `BTOXGR_GP` (baseline) are created to display the correct output.
::: {.panel-tabset .nav-justified group="webr"}
## {{< fa regular file-lines sm fw >}} Preview
```{r variant2, test = list(result_v2 = "result")}
adlb_f <- adlb %>% filter(WGRLOFL == "Y")
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- h_adsl_adlb_merge_using_worst_flag(adsl_f, adlb_f, worst_flag = c("WGRLOFL" = "Y"))
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
mutate(
ATOXGR_GP = factor(case_when(
ATOXGR %in% c(0, 1, 2, 3, 4) ~ "Not Low",
ATOXGR == -1 ~ "1",
ATOXGR == -2 ~ "2",
ATOXGR == -3 ~ "3",
ATOXGR == -4 ~ "4",
ATOXGR == "<Missing>" ~ "Missing"
), levels = c("Not Low", "1", "2", "3", "4", "Missing"))
) %>%
mutate(
BTOXGR_GP = factor(case_when(
BTOXGR %in% c(0, 1, 2, 3, 4) ~ "Not Low",
BTOXGR == -1 ~ "1",
BTOXGR == -2 ~ "2",
BTOXGR == -3 ~ "3",
BTOXGR == -4 ~ "4",
BTOXGR == "<Missing>" ~ "Missing"
), levels = c("Not Low", "1", "2", "3", "4", "Missing"))
)
result <- basic_table(show_colcounts = TRUE) %>%
split_cols_by("ACTARM") %>%
split_rows_by(
"PARAM",
split_fun = drop_split_levels,
label_pos = "topleft",
split_label = "Parameter"
) %>%
split_rows_by(
"BTOXGR_GP",
label_pos = "topleft",
split_label = " Baseline NCI-CTCAE Grade",
indent_mod = 2L
) %>%
summarize_num_patients(var = "USUBJID", .stats = c("unique_count"), unique_count_suffix = FALSE) %>%
count_occurrences_by_grade("ATOXGR_GP", denom = "n", drop = FALSE, .indent_mods = 3L) %>%
append_topleft(" Post-baseline NCI-CTCAE Grade") %>%
build_table(df = adlb_out, alt_counts_df = adsl_f) %>%
prune_table()
result
```
```{r include = FALSE}
webr_code_labels <- c("variant2")
```
{{< include ../../_utils/webr.qmd >}}
:::
## Table Without Patients with <br/> Missing Baseline (High)
Note that missing baseline values are filtered out in the pre-processing step.
::: {.panel-tabset .nav-justified group="webr"}
## {{< fa regular file-lines sm fw >}} Preview
```{r variant3, test = list(result_v3 = "result")}
adlb_f <- adlb %>% filter(WGRHIFL == "Y")
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- h_adsl_adlb_merge_using_worst_flag(adsl_f, adlb_f, worst_flag = c("WGRHIFL" = "Y"))
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
filter(BTOXGR != "<Missing>") %>%
mutate(
ATOXGR_GP = factor(case_when(
ATOXGR %in% c(0, -1, -2, -3, -4) ~ "Not High",
ATOXGR == 1 ~ "1",
ATOXGR == 2 ~ "2",
ATOXGR == 3 ~ "3",
ATOXGR == 4 ~ "4",
ATOXGR == "<Missing>" ~ "Missing"
), levels = c("Not High", "1", "2", "3", "4", "Missing"))
) %>%
mutate(
BTOXGR_GP = factor(case_when(
BTOXGR %in% c(0, -1, -2, -3, -4) ~ "Not High",
BTOXGR == 1 ~ "1",
BTOXGR == 2 ~ "2",
BTOXGR == 3 ~ "3",
BTOXGR == 4 ~ "4"
), levels = c("Not High", "1", "2", "3", "4"))
)
result <- basic_table(show_colcounts = TRUE) %>%
split_cols_by("ACTARM") %>%
split_rows_by(
"PARAM",
split_fun = drop_split_levels,
label_pos = "topleft",
split_label = "Parameter"
) %>%
split_rows_by(
"BTOXGR_GP",
label_pos = "topleft",
split_label = " Baseline NCI-CTCAE Grade",
indent_mod = 2L
) %>%
summarize_num_patients(var = "USUBJID", .stats = c("unique_count"), unique_count_suffix = FALSE) %>%
count_occurrences_by_grade("ATOXGR_GP", denom = "n", drop = FALSE, .indent_mods = 3L) %>%
append_topleft(" Post-baseline NCI-CTCAE Grade") %>%
build_table(df = adlb_out, alt_counts_df = adsl_f) %>%
prune_table()
result
```
```{r include = FALSE}
webr_code_labels <- c("variant3")
```
{{< include ../../_utils/webr.qmd >}}
:::
## Table with Missing Baseline <br/> Considered as Grade 0 (Low)
Note that when BTOXGR is missing, the grouping variable `BTOXGR_GP` now is `"Not Low"` instead of `"Missing"` compared to *Standard Table (Low)*.
::: {.panel-tabset .nav-justified group="webr"}
## {{< fa regular file-lines sm fw >}} Preview
```{r variant4, test = list(result_v4 = "result")}
adlb_f <- adlb %>% filter(WGRLOFL == "Y")
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- h_adsl_adlb_merge_using_worst_flag(adsl_f, adlb_f, worst_flag = c("WGRLOFL" = "Y"))
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
mutate(
ATOXGR_GP = factor(case_when(
ATOXGR %in% c(0, 1, 2, 3, 4) ~ "Not Low",
ATOXGR == -1 ~ "1",
ATOXGR == -2 ~ "2",
ATOXGR == -3 ~ "3",
ATOXGR == -4 ~ "4",
ATOXGR == "<Missing>" ~ "Missing"
), levels = c("Not Low", "1", "2", "3", "4"))
) %>%
mutate(
BTOXGR_GP = factor(case_when(
BTOXGR %in% c(0, 1, 2, 3, 4, "<Missing>") ~ "Not Low",
BTOXGR == -1 ~ "1",
BTOXGR == -2 ~ "2",
BTOXGR == -3 ~ "3",
BTOXGR == -4 ~ "4"
), levels = c("Not Low", "1", "2", "3", "4", "Missing"))
)
result <- basic_table(show_colcounts = TRUE) %>%
split_cols_by("ACTARM") %>%
split_rows_by(
"PARAM",
split_fun = drop_split_levels,
label_pos = "topleft",
split_label = "Parameter"
) %>%
split_rows_by(
"BTOXGR_GP",
label_pos = "topleft",
split_label = " Baseline NCI-CTCAE Grade",
indent_mod = 2L
) %>%
summarize_num_patients(var = "USUBJID", .stats = c("unique_count"), unique_count_suffix = FALSE) %>%
count_occurrences_by_grade("ATOXGR_GP", denom = "n", drop = FALSE, .indent_mods = 3L) %>%
append_topleft(" Post-baseline NCI-CTCAE Grade") %>%
build_table(df = adlb_out, alt_counts_df = adsl_f) %>%
prune_table()
result
```
```{r include = FALSE}
webr_code_labels <- c("variant4")
```
{{< include ../../_utils/webr.qmd >}}
:::
## Table with Fill-In of Grades
Pre-processing is the same as *Standard Table (High)*, but in order to keep all levels, `prune_table()` is not applied.
::: {.panel-tabset .nav-justified group="webr"}
## {{< fa regular file-lines sm fw >}} Preview
```{r variant5, test = list(result_v5 = "result")}
adlb_f <- adlb %>% filter(WGRHIFL == "Y")
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- h_adsl_adlb_merge_using_worst_flag(adsl_f, adlb_f, worst_flag = c("WGRHIFL" = "Y"))
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
mutate(
ATOXGR_GP = factor(case_when(
ATOXGR %in% c(0, -1, -2, -3, -4) ~ "Not High",
ATOXGR == 1 ~ "1",
ATOXGR == 2 ~ "2",
ATOXGR == 3 ~ "3",
ATOXGR == 4 ~ "4",
ATOXGR == "<Missing>" ~ "Missing"
), levels = c("Not High", "1", "2", "3", "4", "Missing"))
) %>%
mutate(
BTOXGR_GP = factor(case_when(
BTOXGR %in% c(0, -1, -2, -3, -4) ~ "Not High",
BTOXGR == 1 ~ "1",
BTOXGR == 2 ~ "2",
BTOXGR == 3 ~ "3",
BTOXGR == 4 ~ "4",
BTOXGR == "<Missing>" ~ "Missing"
), levels = c("Not High", "1", "2", "3", "4", "Missing"))
)
result <- basic_table(show_colcounts = TRUE) %>%
split_cols_by("ACTARM") %>%
split_rows_by(
"PARAM",
split_fun = drop_split_levels,
label_pos = "topleft",
split_label = "Parameter"
) %>%
split_rows_by(
"BTOXGR_GP",
label_pos = "topleft",
split_label = " Baseline NCI-CTCAE Grade",
indent_mod = 2L
) %>%
summarize_num_patients(var = "USUBJID", .stats = c("unique_count"), unique_count_suffix = FALSE) %>%
count_occurrences_by_grade("ATOXGR_GP", denom = "n", drop = FALSE, .indent_mods = 3L) %>%
append_topleft(" Post-baseline NCI-CTCAE Grade") %>%
build_table(df = adlb_out, alt_counts_df = adsl_f)
result
```
```{r include = FALSE}
webr_code_labels <- c("variant5")
```
{{< include ../../_utils/webr.qmd >}}
:::
## Data Setup
Please note that for each variant, the `adlb` dataset needs to be filtered on correct flags like `WGRLOFL` , `WGRHIFL` , et al., otherwise the layout function will not return the correct counts. There is an option to create a record for a lab test where no record is found at that visit. If you specified `add_derived_type = "PHANTOM"` & `dtype_phantom_cond` , you don't have to use the `h_adsl_adlb_merge_using_worst_flag` function to preprocess your `adlb` dataset. Otherwise please follow the pre-processing steps below before applying the layout functions.
```{r setup}
#| code-fold: show
```
::::::::
{{< include ../../_utils/save_results.qmd >}}
## `teal` App
::: {.panel-tabset .nav-justified}
## {{< fa regular file-lines fa-sm fa-fw >}} Preview
```{r teal, opts.label = c("skip_if_testing", "app")}
library(teal.modules.clinical)
## Data reproducible code
data <- teal_data()
data <- within(data, {
ADSL <- random.cdisc.data::cadsl
ADLB <- random.cdisc.data::cadlb
})
datanames <- c("ADSL", "ADLB")
datanames(data) <- datanames
join_keys(data) <- default_cdisc_join_keys[datanames]
## Reusable Configuration For Modules
ADSL <- data[["ADSL"]]
ADLB <- data[["ADLB"]]
## Setup App
app <- init(
data = data,
modules = modules(
tm_t_shift_by_grade(
label = "Grade Laboratory Abnormality Table",
dataname = "ADLB",
arm_var = choices_selected(
choices = variable_choices(ADSL, subset = c("ARM", "ARMCD")),
selected = "ARM"
),
paramcd = choices_selected(
choices = value_choices(ADLB, "PARAMCD", "PARAM"),
selected = "ALT"
),
worst_flag_var = choices_selected(
choices = variable_choices(ADLB, subset = c("WGRLOVFL", "WGRLOFL", "WGRHIVFL", "WGRHIFL")),
selected = c("WGRHIFL")
),
worst_flag_indicator = choices_selected(
value_choices(ADLB, "WGRLOVFL"),
selected = "Y", fixed = TRUE
),
anl_toxgrade_var = choices_selected(
choices = variable_choices(ADLB, subset = c("ATOXGR")),
selected = c("ATOXGR"),
fixed = TRUE
),
base_toxgrade_var = choices_selected(
choices = variable_choices(ADLB, subset = c("BTOXGR")),
selected = c("BTOXGR"),
fixed = TRUE
),
add_total = FALSE
)
),
filter = teal_slices(teal_slice("ADSL", "SAFFL", selected = "Y"))
)
shinyApp(app$ui, app$server)
```
{{< include ../../_utils/shinylive.qmd >}}
:::
{{< include ../../repro.qmd >}}