---
title: LBT13
subtitle: NCI CTCAE Grade Laboratory Abnormalities by Visit and Baseline Grade
---
------------------------------------------------------------------------
{{< include ../../_utils/envir_hook.qmd >}}
:::: {.panel-tabset}
```{r setup, echo = 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")
```
## 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 = 3L) %>%
build_table(df = adlb_out, alt_counts_df = adsl_f)
result
```
`r webr_code_labels <- c("setup", "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 = 3L) %>%
build_table(df = adlb_out, alt_counts_df = adsl_f)
result
```
`r webr_code_labels <- c("setup", "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 = 3L) %>%
build_table(df = adlb_out, alt_counts_df = adsl_f)
result
```
`r webr_code_labels <- c("setup", "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 = 3L) %>%
build_table(df = adlb_out, alt_counts_df = adsl_f)
result
```
`r webr_code_labels <- c("setup", "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 = 3L) %>%
build_table(df = adlb_out, alt_counts_df = adsl_f)
result
```
`r webr_code_labels <- c("setup", "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 >}}