---
title: LBT13
subtitle: NCI CTCAE Grade Laboratory Abnormalities by Visit and Baseline 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 (PARAMCD == "CRP" & SAFFL == "Y" )
```
```{r include = FALSE}
webr_code_labels <- c ("setup" )
```
{{< include ../../_utils/webr_no_include.qmd >}}
## Output
:::::::: panel-tabset
## Standard Table (Low)
Note that the worst laboratory flag (below `WGRLOVFL` ) must be selected appropriately to match the direction of abnormality (here `Low` ). New grouping variables `ATOXGR_GP` and `BTOXGR_GP` 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 (WGRLOVFL == "Y" )
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- adsl_f %>%
h_adsl_adlb_merge_using_worst_flag (
adlb_f,
worst_flag = c ("WGRLOVFL" = "Y" ),
by_visit = TRUE ,
no_fillin_visits = c ("SCREENING" , "BASELINE" , "UNSCHEDULED" )
)
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
mutate (
ATOXGR_GP = 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"
)
) %>%
mutate (
BTOXGR_GP = 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"
)
)
adlb_out <- adlb_out %>% mutate (
AVISIT = forcats:: fct_reorder (AVISIT, AVISITN),
ATOXGR_GP = factor (ATOXGR_GP, levels = c ("Not Low" , "1" , "2" , "3" , "4" , "Missing" )),
BTOXGR_GP = factor (BTOXGR_GP, levels = c ("Not Low" , "1" , "2" , "3" , "4" , "Missing" ))
)
adlb_out <- adlb_out %>%
var_relabel (
PARAMCD = "Parameter Code" ,
AVISIT = "Visit" ,
ATOXGR_GP = "NCI CTCAE Grade at Visit" ,
BTOXGR_GP = "Baseline NCI CTCAE Grade"
)
result <- basic_table (show_colcounts = TRUE ) %>%
split_cols_by ("ACTARM" ) %>%
split_rows_by (
"PARAMCD" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ PARAMCD)
) %>%
split_rows_by (
"AVISIT" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ AVISIT)
) %>%
split_rows_by (
"ATOXGR_GP" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ ATOXGR_GP)
) %>%
summarize_num_patients (var = "USUBJID" , .stats = c ("unique_count" )) %>%
count_occurrences ("BTOXGR_GP" , denom = "n" , drop = TRUE ) %>%
append_varlabels (adlb_out, "BTOXGR_GP" , indent = 3 L) %>%
build_table (df = adlb_out, alt_counts_df = adsl_f)
result
```
```{r include = FALSE}
webr_code_labels <- c ("variant1" )
```
{{< include ../../_utils/webr.qmd >}}
:::
## Standard Table (High)
Note that the worst laboratory flag (below `WGRHIVFL` ) must be selected appropriately to match the direction of abnormality (here `High` ). New grouping variables `ATOXGR_GP` and `BTOXGR_GP` 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 (WGRHIVFL == "Y" )
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- adsl_f %>%
h_adsl_adlb_merge_using_worst_flag (
adlb_f,
worst_flag = c ("WGRHIVFL" = "Y" ),
by_visit = TRUE ,
no_fillin_visits = c ("SCREENING" , "BASELINE" , "UNSCHEDULED" )
)
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
mutate (
ATOXGR_GP = 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"
)
) %>%
mutate (
BTOXGR_GP = 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"
)
)
adlb_out <- adlb_out %>% mutate (
AVISIT = forcats:: fct_reorder (AVISIT, AVISITN),
ATOXGR_GP = factor (ATOXGR_GP, levels = c ("Not High" , "1" , "2" , "3" , "4" , "Missing" )),
BTOXGR_GP = factor (BTOXGR_GP, levels = c ("Not High" , "1" , "2" , "3" , "4" , "Missing" ))
)
adlb_out <- adlb_out %>%
var_relabel (
PARAMCD = "Parameter Code" ,
AVISIT = "Visit" ,
ATOXGR_GP = "NCI CTCAE Grade at Visit" ,
BTOXGR_GP = "Baseline NCI CTCAE Grade"
)
result <- basic_table (show_colcounts = TRUE ) %>%
split_cols_by ("ACTARM" ) %>%
split_rows_by (
"PARAMCD" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ PARAMCD)
) %>%
split_rows_by (
"AVISIT" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ AVISIT)
) %>%
split_rows_by (
"ATOXGR_GP" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ ATOXGR_GP)
) %>%
summarize_num_patients (var = "USUBJID" , .stats = c ("unique_count" )) %>%
count_occurrences ("BTOXGR_GP" , denom = "n" , drop = TRUE ) %>%
append_varlabels (adlb_out, "BTOXGR_GP" , indent = 3 L) %>%
build_table (df = adlb_out, alt_counts_df = adsl_f)
result
```
```{r include = FALSE}
webr_code_labels <- c ("variant2" )
```
{{< include ../../_utils/webr.qmd >}}
:::
## Table Without Patients with <br/> Missing Baseline (Low)
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 (WGRLOVFL == "Y" )
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- adsl_f %>%
h_adsl_adlb_merge_using_worst_flag (
adlb_f,
worst_flag = c ("WGRLOVFL" = "Y" ),
by_visit = TRUE ,
no_fillin_visits = c ("SCREENING" , "BASELINE" , "UNSCHEDULED" )
)
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
filter (BTOXGR != "<Missing>" ) %>% # filter out missing baseline grade
mutate (
ATOXGR_GP = 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"
)
) %>%
mutate (
BTOXGR_GP = case_when (
BTOXGR %in% c (0 , 1 , 2 , 3 , 4 ) ~ "Not Low" ,
BTOXGR == - 1 ~ "1" ,
BTOXGR == - 2 ~ "2" ,
BTOXGR == - 3 ~ "3" ,
BTOXGR == - 4 ~ "4"
)
)
adlb_out <- adlb_out %>% mutate (
AVISIT = forcats:: fct_reorder (AVISIT, AVISITN),
ATOXGR_GP = factor (ATOXGR_GP, levels = c ("Not Low" , "1" , "2" , "3" , "4" , "Missing" )),
BTOXGR_GP = factor (BTOXGR_GP, levels = c ("Not Low" , "1" , "2" , "3" , "4" ))
)
adlb_out <- adlb_out %>%
var_relabel (
PARAMCD = "Parameter Code" ,
AVISIT = "Visit" ,
ATOXGR_GP = "NCI CTCAE Grade at Visit" ,
BTOXGR_GP = "Baseline NCI CTCAE Grade"
)
result <- basic_table (show_colcounts = TRUE ) %>%
split_cols_by ("ACTARM" ) %>%
split_rows_by (
"PARAMCD" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ PARAMCD)
) %>%
split_rows_by (
"AVISIT" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ AVISIT)
) %>%
split_rows_by (
"ATOXGR_GP" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ ATOXGR_GP)
) %>%
summarize_num_patients (var = "USUBJID" , .stats = c ("unique_count" )) %>%
count_occurrences ("BTOXGR_GP" , denom = "n" , drop = TRUE ) %>%
append_varlabels (adlb_out, "BTOXGR_GP" , indent = 3 L) %>%
build_table (df = adlb_out, alt_counts_df = adsl_f)
result
```
```{r include = FALSE}
webr_code_labels <- c ("variant3" )
```
{{< include ../../_utils/webr.qmd >}}
:::
## Table with Missing Baseline <br/> Considered as Grade 0 (High)
Note that when `BTOXGR` is missing, the grouping variable `BTOXGR_GP` is now `"Not High"` instead of `"Missing"` compared to *Standard Table (High)*.
::: {.panel-tabset .nav-justified group="webr"}
## {{< fa regular file-lines sm fw >}} Preview
```{r variant4, test = list(result_v4 = "result")}
adlb_f <- adlb %>% filter (WGRHIVFL == "Y" )
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- adsl_f %>%
h_adsl_adlb_merge_using_worst_flag (
adlb_f,
worst_flag = c ("WGRHIVFL" = "Y" ),
by_visit = TRUE ,
no_fillin_visits = c ("SCREENING" , "BASELINE" , "UNSCHEDULED" )
)
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
mutate (
ATOXGR_GP = 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"
)
) %>%
mutate (
BTOXGR_GP = case_when (
BTOXGR %in% c (0 , - 1 , - 2 , - 3 , - 4 , "<Missing>" ) ~ "Not High" , # Missing BTOXGR now grouped to "Not High"
BTOXGR == 1 ~ "1" ,
BTOXGR == 2 ~ "2" ,
BTOXGR == 3 ~ "3" ,
BTOXGR == 4 ~ "4"
)
)
adlb_out <- adlb_out %>% mutate (
AVISIT = forcats:: fct_reorder (AVISIT, AVISITN),
ATOXGR_GP = factor (ATOXGR_GP, levels = c ("Not High" , "1" , "2" , "3" , "4" , "Missing" )),
BTOXGR_GP = factor (BTOXGR_GP, levels = c ("Not High" , "1" , "2" , "3" , "4" , "Missing" ))
)
adlb_out <- adlb_out %>%
var_relabel (
PARAMCD = "Parameter Code" ,
AVISIT = "Visit" ,
ATOXGR_GP = "NCI CTCAE Grade at Visit" ,
BTOXGR_GP = "Baseline NCI CTCAE Grade"
)
result <- basic_table (show_colcounts = TRUE ) %>%
split_cols_by ("ACTARM" ) %>%
split_rows_by (
"PARAMCD" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ PARAMCD)
) %>%
split_rows_by (
"AVISIT" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ AVISIT)
) %>%
split_rows_by (
"ATOXGR_GP" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ ATOXGR_GP)
) %>%
summarize_num_patients (var = "USUBJID" , .stats = c ("unique_count" )) %>%
count_occurrences ("BTOXGR_GP" , denom = "n" , drop = TRUE ) %>%
append_varlabels (adlb_out, "BTOXGR_GP" , indent = 3 L) %>%
build_table (df = adlb_out, alt_counts_df = adsl_f)
result
```
```{r include = FALSE}
webr_code_labels <- c ("variant4" )
```
{{< include ../../_utils/webr.qmd >}}
:::
## Table with Fill-In <br/> of Grades (High)
Pre-processing is the same as for *Standard Table (High)*, but in order to keep all levels, the `drop` argument in `count_occurrences` is set to `FALSE` .
::: {.panel-tabset .nav-justified group="webr"}
## {{< fa regular file-lines sm fw >}} Preview
```{r variant5, test = list(result_v5 = "result")}
adlb_f <- adlb %>% filter (WGRHIVFL == "Y" )
# Please note the step below can be skipped if you are using DTYPE PHANTOM
adlb_out <- adsl_f %>%
h_adsl_adlb_merge_using_worst_flag (
adlb_f,
worst_flag = c ("WGRHIVFL" = "Y" ),
by_visit = TRUE ,
no_fillin_visits = c ("SCREENING" , "BASELINE" , "UNSCHEDULED" )
)
# Create new grouping variables ATOXGR_GP, BTOXGR_GP
adlb_out <- adlb_out %>%
mutate (
ATOXGR_GP = 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"
)
) %>%
mutate (
BTOXGR_GP = 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"
)
)
adlb_out <- adlb_out %>% mutate (
AVISIT = forcats:: fct_reorder (AVISIT, AVISITN),
ATOXGR_GP = factor (ATOXGR_GP, levels = c ("Not High" , "1" , "2" , "3" , "4" , "Missing" )),
BTOXGR_GP = factor (BTOXGR_GP, levels = c ("Not High" , "1" , "2" , "3" , "4" , "Missing" ))
)
adlb_out <- adlb_out %>%
var_relabel (
PARAMCD = "Parameter Code" ,
AVISIT = "Visit" ,
ATOXGR_GP = "NCI CTCAE Grade at Visit" ,
BTOXGR_GP = "Baseline NCI CTCAE Grade"
)
result <- basic_table (show_colcounts = TRUE ) %>%
split_cols_by ("ACTARM" ) %>%
split_rows_by (
"PARAMCD" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ PARAMCD)
) %>%
split_rows_by (
"AVISIT" ,
split_fun = drop_split_levels, label_pos = "topleft" , split_label = obj_label (adlb_out$ AVISIT)
) %>%
split_rows_by (
"ATOXGR_GP" ,
split_fun = keep_split_levels (c ("Not High" , "1" , "2" , "3" , "4" , "Missing" )),
label_pos = "topleft" ,
split_label = obj_label (adlb_out$ ATOXGR_GP)
) %>%
summarize_num_patients (var = "USUBJID" , .stats = c ("unique_count" )) %>%
count_occurrences ("BTOXGR_GP" , denom = "n" , drop = FALSE ) %>%
append_varlabels (adlb_out, "BTOXGR_GP" , indent = 3 L) %>%
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 `WGRLOVFL` , `WGRHIVFL` , 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 ("WGRLOVFL" )
),
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 >}}