---
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 = 2 L
) %>%
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 = 3 L) %>%
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 = 2 L
) %>%
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 = 3 L) %>%
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 = 2 L
) %>%
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 = 3 L) %>%
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 = 2 L
) %>%
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 = 3 L) %>%
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 = 2 L
) %>%
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 = 3 L) %>%
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 >}}