The LBT03 template is the result of a junction between the analysis of AVAL at baseline and CHG at visit time. AVAL is summarized for baseline visits and and CHG is summarized for post-baseline visits.
A: Drug X B: Placebo C: Combination
Analysis Visit (N=134) (N=134) (N=132)
—————————————————————————————————————————————————————————————
BASELINE
n 134 134 132
Mean (SD) 9.06 (0.93) 8.99 (0.98) 8.98 (0.89)
Median 9.07 8.92 8.96
Min - Max 6.21 - 11.87 6.23 - 11.63 6.24 - 11.18
WEEK 1 DAY 8
n 134 0 132
Mean (SD) -0.05 (1.38) NA -0.02 (1.30)
Median -0.17 NA 0.02
Min - Max -3.56 - 3.48 NA -3.28 - 3.33
WEEK 2 DAY 15
n 134 134 132
Mean (SD) -0.19 (1.47) 0.01 (1.45) 0.15 (1.25)
Median -0.27 -0.00 0.15
Min - Max -4.53 - 4.45 -3.79 - 3.43 -2.92 - 3.28
WEEK 3 DAY 22
n 134 134 132
Mean (SD) 0.03 (1.38) -0.02 (1.49) 0.02 (1.34)
Median 0.15 -0.04 0.20
Min - Max -3.95 - 2.99 -4.28 - 4.24 -2.76 - 3.26
WEEK 4 DAY 29
n 134 134 132
Mean (SD) -0.26 (1.45) 0.05 (1.24) -0.01 (1.17)
Median -0.37 0.10 -0.06
Min - Max -3.74 - 4.15 -3.34 - 3.71 -3.06 - 3.22
WEEK 5 DAY 36
n 134 134 132
Mean (SD) -0.02 (1.50) 0.07 (1.34) 0.03 (1.27)
Median 0.01 0.15 0.05
Min - Max -4.15 - 3.96 -3.50 - 3.53 -3.63 - 4.78
Experimental use!
WebR is a tool allowing you to run R code in the web browser. Modify the code below and click run to see the results. Alternatively, copy the code and click here to open WebR in a new tab.
In the final step, a new variable is derived from AVISIT that can specify the method of estimation of the evaluated change.
adlb_f <- adlb_f %>%mutate(AVISIT_header =recode(AVISIT,"BASELINE"="BASELINE","WEEK 1 DAY 8"="WEEK 1 DAY 8 value minus baseline","WEEK 2 DAY 15"="WEEK 2 DAY 15 value minus baseline","WEEK 3 DAY 22"="WEEK 3 DAY 22 value minus baseline","WEEK 4 DAY 29"="WEEK 4 DAY 29 value minus baseline","WEEK 5 DAY 36"="WEEK 5 DAY 36 value minus baseline"))# Define the split functionsplit_fun <- drop_split_levelslyt <-basic_table(show_colcounts =TRUE) %>%split_cols_by("ARM") %>%split_rows_by("AVISIT_header",split_fun = split_fun,label_pos ="topleft",split_label =obj_label(adlb_f$AVISIT) ) %>%summarize_change("CHG",variables =list(value ="AVAL", baseline_flag ="ABLFLL"),na.rm =TRUE )result <-build_table(lyt = lyt,df = adlb_f,alt_counts_df = adsl)result
A: Drug X B: Placebo C: Combination
Analysis Visit (N=134) (N=134) (N=132)
—————————————————————————————————————————————————————————————————————————————————
BASELINE
n 134 134 132
Mean (SD) 9.06 (0.93) 8.99 (0.98) 8.98 (0.89)
Median 9.07 8.92 8.96
Min - Max 6.21 - 11.87 6.23 - 11.63 6.24 - 11.18
WEEK 1 DAY 8 value minus baseline
n 134 0 132
Mean (SD) -0.05 (1.38) NA -0.02 (1.30)
Median -0.17 NA 0.02
Min - Max -3.56 - 3.48 NA -3.28 - 3.33
WEEK 2 DAY 15 value minus baseline
n 134 134 132
Mean (SD) -0.19 (1.47) 0.01 (1.45) 0.15 (1.25)
Median -0.27 -0.00 0.15
Min - Max -4.53 - 4.45 -3.79 - 3.43 -2.92 - 3.28
WEEK 3 DAY 22 value minus baseline
n 134 134 132
Mean (SD) 0.03 (1.38) -0.02 (1.49) 0.02 (1.34)
Median 0.15 -0.04 0.20
Min - Max -3.95 - 2.99 -4.28 - 4.24 -2.76 - 3.26
WEEK 4 DAY 29 value minus baseline
n 134 134 132
Mean (SD) -0.26 (1.45) 0.05 (1.24) -0.01 (1.17)
Median -0.37 0.10 -0.06
Min - Max -3.74 - 4.15 -3.34 - 3.71 -3.06 - 3.22
WEEK 5 DAY 36 value minus baseline
n 134 134 132
Mean (SD) -0.02 (1.50) 0.07 (1.34) 0.03 (1.27)
Median 0.01 0.15 0.05
Min - Max -4.15 - 3.96 -3.50 - 3.53 -3.63 - 4.78
Experimental use!
WebR is a tool allowing you to run R code in the web browser. Modify the code below and click run to see the results. Alternatively, copy the code and click here to open WebR in a new tab.
For illustration purposes, this example focuses on “C-Reactive Protein Measurement” starting from baseline, while excluding visit at week 1 for subjects who were randomized to the placebo group.
Code
library(dplyr)library(tern)adsl <- random.cdisc.data::cadsladlb <- random.cdisc.data::cadlb# Ensure character variables are converted to factors and empty strings and NAs are explicit missing levels.adsl <-df_explicit_na(adsl)adlb <-df_explicit_na(adlb)saved_labels <-var_labels(adlb)adlb_f <- adlb %>%filter( PARAM =="C-Reactive Protein Measurement",!(ARM =="B: Placebo"& AVISIT =="WEEK 1 DAY 8"), AVISIT !="SCREENING" ) %>% dplyr::mutate(AVISIT =droplevels(AVISIT),ABLFLL = ABLFL =="Y" )var_labels(adlb_f) <-c(saved_labels, "")
Here, we pre-process and manually define the variable “Baseline or Absolute Change from Baseline”.
Code
library(teal.modules.clinical)## Data reproducible codedata <-teal_data()data <-within(data, { ADSL <-df_explicit_na(random.cdisc.data::cadsl) ADLB <-df_explicit_na(random.cdisc.data::cadlb) %>%filter(!(ARM =="B: Placebo"& AVISIT =="WEEK 1 DAY 8"), AVISIT !="SCREENING" ) %>%mutate(AVISIT =droplevels(AVISIT),ABLFLL = ABLFL =="Y",AVISIT_header =recode(AVISIT,"BASELINE"="BASELINE","WEEK 1 DAY 8"="WEEK 1 DAY 8 value minus baseline","WEEK 2 DAY 15"="WEEK 2 DAY 15 value minus baseline","WEEK 3 DAY 22"="WEEK 3 DAY 22 value minus baseline","WEEK 4 DAY 29"="WEEK 4 DAY 29 value minus baseline","WEEK 5 DAY 36"="WEEK 5 DAY 36 value minus baseline" ) ) %>%group_by(USUBJID, PARAM) %>%mutate(AVAL_CHG = AVAL - (!ABLFLL) *sum(AVAL * ABLFLL) ) %>%ungroup() %>%col_relabel(AVAL_CHG ="Baseline or Absolute Change from Baseline",ABLFLL ="Baseline Flag (TRUE/FALSE)",AVISIT_header ="Analysis Visit" )})datanames <-c("ADSL", "ADLB")datanames(data) <- datanamesjoin_keys(data) <- default_cdisc_join_keys[datanames]## Reusable Configuration For ModulesADSL <- data[["ADSL"]]ADLB <- data[["ADLB"]]## Setup Appapp <-init(data = data,modules =modules(tm_t_summary_by(label ="Laboratory Test Results Change from Baseline by Visit",dataname ="ADLB",arm_var =choices_selected(choices =variable_choices(ADSL, c("ARM", "ARMCD")),selected ="ARM" ),by_vars =choices_selected(# note: order matters here. If `PARAM` is first, the split will be first by `PARAM`and then by `AVISIT`choices =variable_choices(ADLB, c("PARAM", "AVISIT_header")),selected =c("PARAM", "AVISIT_header") ),summarize_vars =choices_selected(choices =variable_choices(ADLB, c("AVAL", "CHG", "AVAL_CHG")),selected =c("AVAL_CHG") ),useNA ="ifany",paramcd =choices_selected(choices =value_choices(ADLB, "PARAMCD", "PARAM"),selected ="CRP" ) ) ),filter =teal_slices(teal_slice("ADLB", "AVAL", selected =NULL)))shinyApp(app$ui, app$server)
Warning: The 'plotly_relayout' event tied a source ID of
'teal-main_ui-filter_panel-active-ADLB-filter-ADLB_AVAL-inputs-histogram_plot'
is not registered. In order to obtain this event data, please add
`event_register(p, 'plotly_relayout')` to the plot (`p`) that you wish to
obtain event data from.
Experimental use!
shinylive allow you to modify to run shiny application entirely in the web browser. Modify the code below and click re-run the app to see the results. The performance is slighly worse and some of the features (e.g. downloading) might not work at all.
#| standalone: true#| viewerHeight: 800#| editorHeight: 200#| components: [viewer, editor]#| layout: vertical# -- WEBR HELPERS --options(webr_pkg_repos = c("r-universe" = "https://insightsengineering.r-universe.dev", getOption("webr_pkg_repos")))# -- APP CODE --library(teal.modules.clinical)## Data reproducible codedata <- teal_data()data <- within(data, { ADSL <- df_explicit_na(random.cdisc.data::cadsl) ADLB <- df_explicit_na(random.cdisc.data::cadlb) %>% filter( !(ARM == "B: Placebo" & AVISIT == "WEEK 1 DAY 8"), AVISIT != "SCREENING" ) %>% mutate( AVISIT = droplevels(AVISIT), ABLFLL = ABLFL == "Y", AVISIT_header = recode(AVISIT, "BASELINE" = "BASELINE", "WEEK 1 DAY 8" = "WEEK 1 DAY 8 value minus baseline", "WEEK 2 DAY 15" = "WEEK 2 DAY 15 value minus baseline", "WEEK 3 DAY 22" = "WEEK 3 DAY 22 value minus baseline", "WEEK 4 DAY 29" = "WEEK 4 DAY 29 value minus baseline", "WEEK 5 DAY 36" = "WEEK 5 DAY 36 value minus baseline" ) ) %>% group_by(USUBJID, PARAM) %>% mutate( AVAL_CHG = AVAL - (!ABLFLL) * sum(AVAL * ABLFLL) ) %>% ungroup() %>% col_relabel( AVAL_CHG = "Baseline or Absolute Change from Baseline", ABLFLL = "Baseline Flag (TRUE/FALSE)", AVISIT_header = "Analysis Visit" )})datanames <- c("ADSL", "ADLB")datanames(data) <- datanamesjoin_keys(data) <- default_cdisc_join_keys[datanames]## Reusable Configuration For ModulesADSL <- data[["ADSL"]]ADLB <- data[["ADLB"]]## Setup Appapp <- init( data = data, modules = modules( tm_t_summary_by( label = "Laboratory Test Results Change from Baseline by Visit", dataname = "ADLB", arm_var = choices_selected( choices = variable_choices(ADSL, c("ARM", "ARMCD")), selected = "ARM" ), by_vars = choices_selected( # note: order matters here. If `PARAM` is first, the split will be first by `PARAM`and then by `AVISIT` choices = variable_choices(ADLB, c("PARAM", "AVISIT_header")), selected = c("PARAM", "AVISIT_header") ), summarize_vars = choices_selected( choices = variable_choices(ADLB, c("AVAL", "CHG", "AVAL_CHG")), selected = c("AVAL_CHG") ), useNA = "ifany", paramcd = choices_selected( choices = value_choices(ADLB, "PARAMCD", "PARAM"), selected = "CRP" ) ) ), filter = teal_slices(teal_slice("ADLB", "AVAL", selected = NULL)))shinyApp(app$ui, app$server)