
exposure-duration-histogram
exposure-duration-histogram.Rmd
Create Exposure Duration Histogram
The plotly_exp_duration() function provides an interactive visualization of subject-level exposure duration in clinical trials. This histogram helps assess how long participants remained on treatment, with configurable duration categories such as “≥1 day”, “≥7 days”, “≥28 days”, and so on.
Using pre-processed output from prepare_exp_duration() (and optionally extend_exp_duration()), plotly_exp_duration() generates an intuitive, browser-based plot built with Plotly. Users can customize the display type (e.g., counts or proportions), color, tooltip summary statistics, and axis labels.
meta_sl_exposure_example
: create example exposure metadata (meta
object) for demonstration or testing purposes.prepare_exp_duration
: process subject-level exposure data to calculate treatment duration and prepare it for further analysis.extend_exp_duration
: categorize duration into user-defined time windows (e.g., ≥7 days, ≥12 weeks) and add group-level summaries.plotly_exp_duration
: generate an interactive histogram plot to visualize exposure duration distribution across subjects or treatment arms.
meta_sl_exposure_example()
There are two steps in meta_sl_exposure_example
function
in order to build the metadata (meta
object): processing
the ADaM dataset and save meta information for A&R reporting.
Step1: ADEXSUM, the ADaM dataset for Drug Exposrue Summary Data, is utilized to:
- Sum up duration by STUDYID SITENUM USUBJID SUBJID APERIOD EXTRT ADOSEFRM PARAMCD.
- Subset the exposure data by
upcase(trim(left(paramcd))) = "TRTDUR"
. - Get the exposure duration
adexsum$AVAL
for all participants. - Assign duration category
adexsum$EXDURGR
i.e.”>=1 day”, “>=7 days”,“>=28 days”, “>=12 weeks” and “>=24 weeks”.
adsl <- r2rtf::r2rtf_adsl
adexsum <- data.frame(USUBJID = adsl$USUBJID)
adexsum$TRTA <- factor(adsl$TRT01A,
levels = c("Placebo", "Xanomeline Low Dose", "Xanomeline High Dose"),
labels = c("Placebo", "Low Dose", "High Dose")
)
adexsum$APERIODC <- "Base"
adexsum$APERIOD <- 1
set.seed(123) # Set a seed for reproducibility
adexsum$AVAL <- sample(x = 0:(24 * 7), size = length(adexsum$USUBJID), replace = TRUE)
adexsum$EXDURGR <- "not treated"
adexsum$EXDURGR[adexsum$AVAL >= 1] <- ">=1 day"
adexsum$EXDURGR[adexsum$AVAL >= 7] <- ">=7 days"
adexsum$EXDURGR[adexsum$AVAL >= 28] <- ">=28 days"
adexsum$EXDURGR[adexsum$AVAL >= 12 * 7] <- ">=12 weeks"
adexsum$EXDURGR[adexsum$AVAL >= 24 * 7] <- ">=24 weeks"
adexsum$EXDURGR <- factor(adexsum$EXDURGR,
levels = c("not treated", ">=1 day", ">=7 days", ">=28 days", ">=12 weeks", ">=24 weeks")
)
unique(adexsum$EXDURGR)
#> [1] >=12 weeks >=7 days >=28 days >=1 day >=24 weeks not treated
#> Levels: not treated >=1 day >=7 days >=28 days >=12 weeks >=24 weeks
Step2: Save analysis plan and metadata(parameter and analysis) information, then build meta object.
plan <- metalite::plan(
analysis = "exp_dur", population = "apat",
observation = "apat", parameter = "expdur"
)
meta <- metalite::meta_adam(
population = adexsum,
observation = adexsum
) |>
metalite::define_plan(plan) |>
metalite::define_population(
name = "apat",
group = "TRTA",
subset = quote(APERIOD == 1 & AVAL > 0)
) |>
metalite::define_parameter(
name = "expdur",
var = "AVAL",
label = "Exposure Duration (Days)",
vargroup = "EXDURGR"
) |>
metalite::define_analysis(
name = "exp_dur",
title = "Summary of Exposure Duration",
label = "exposure duration table"
) |>
metalite::meta_build()
prepare_exp_duration()
The input of the function prepare_exp_duration()
is a
meta
object created by the metalite package. The resulting
output comprises a collection of raw datasets for analysis and
reporting.
This function takes raw data (e.g., participant-level data with exposure durations and treatment groups). It calculates summary statistics (counts, proportions, medians, etc.) grouped by treatment group. It also creates exposure duration categories (e.g., >=1 day, >=7 days, etc.) by binning or categorizing the raw exposure duration variable. The output is a structured dataset (outdata) that contains: Counts and proportions of participants in each treatment group. Summary statistics for the exposure duration variable within each treatment group. However, at this stage, the statistics are grouped only by treatment group, not yet broken down by exposure duration categories.
outdata <- prepare_exp_duration(meta)
outdata
#> List of 14
#> $ meta :List of 7
#> $ population : chr "apat"
#> $ observation : chr "apat"
#> $ parameter : chr "expdur"
#> $ n :'data.frame': 1 obs. of 6 variables:
#> $ order : NULL
#> $ group : chr "TRTA"
#> $ reference_group: NULL
#> $ char_n :List of 1
#> $ char_var : chr "AVAL"
#> $ char_prop :List of 1
#> $ var_type :List of 1
#> $ group_label : Factor w/ 3 levels "Placebo","Low Dose",..: 1 3 2
#> $ analysis : chr "exp_dur"
Number of participants in population
outdata$n[, 1:5]
#> name n_1 n_2 n_3 n_9999
#> 1 Participants in population 86 83 84 253
Number of participants in each duration category
charn <- data.frame(outdata$char_n[1])
head(charn[, 1:5], 6)
#> name Placebo Low.Dose High.Dose Total
#> 1 not treated 0 0 0 0
#> 2 >=1 day 2 4 3 9
#> 3 >=7 days 13 11 9 33
#> 4 >=28 days 31 20 27 78
#> 5 >=12 weeks 39 48 45 132
#> 6 >=24 weeks 1 0 0 1
Proportion of participants in each duration category
charp <- data.frame(outdata$char_prop[1])
head(charp[, 1:5], 6)
#> name Placebo Low.Dose High.Dose Total
#> 1 not treated 0.000000 0.000000 0.000000 0.0000000
#> 2 >=1 day 2.325581 4.819277 3.571429 3.5573123
#> 3 >=7 days 15.116279 13.253012 10.714286 13.0434783
#> 4 >=28 days 36.046512 24.096386 32.142857 30.8300395
#> 5 >=12 weeks 45.348837 57.831325 53.571429 52.1739130
#> 6 >=24 weeks 1.162791 0.000000 0.000000 0.3952569
Statistical summary of exposure duration for each treatment
chars <- data.frame(outdata$char_n[1])
tail(chars[, 1:5], 8)
#> name Placebo Low.Dose High.Dose Total
#> 8 Mean 81.5 90.8 87.6 86.6
#> 9 SD 49.1 51.3 48.8 49.7
#> 10 SE 5.3 5.6 5.3 3.1
#> 11 Median 76.0 93.0 90.0 88.0
#> 12 Min 3.0 1.0 4.0 1.0
#> 13 Max 168.0 167.0 167.0 168.0
#> 14 Q1 to Q3 41.25 to 123.25 48 to 137.5 44.75 to 129.25 44 to 133
#> 15 Range 3 to 168 1 to 167 4 to 167 1 to 168
extend_exp_duration()
This function takes the output of prepare_exp_duration() and further processes the data to create exposure duration categories explicitly. It applies the specified duration category cutoffs (e.g., >=1 day, >=7 days, etc.) to the exposure duration variable. It calculates counts, proportions, and summary statistics for each exposure duration category within each treatment group. This means now we have a two-dimensional grouping: By treatment group (e.g., Placebo, Low Dose and High Dose). By exposure duration category (e.g., >=1 day, >=7 days). The output outdata now contains tables like: char_n: counts by exposure duration category and treatment group. char_prop: proportions by exposure duration category and treatment group. char_stat_groups: summary statistics by exposure duration category and treatment group.
outdata <- meta |>
prepare_exp_duration() |>
extend_exp_duration(
duration_category_list = list(c(1, NA), c(7, NA), c(28, NA), c(12 * 7, NA), c(24 * 7, NA)),
duration_category_labels = c(">=1 day", ">=7 days", ">=28 days", ">=12 weeks", ">=24 weeks")
)
outdata
#> List of 19
#> $ meta :List of 7
#> $ population : chr "apat"
#> $ observation : chr "apat"
#> $ parameter : chr "expdur"
#> $ n :'data.frame': 1 obs. of 6 variables:
#> $ order : NULL
#> $ group : chr "TRTA"
#> $ reference_group : NULL
#> $ char_n :List of 1
#> $ char_var : chr "AVAL"
#> $ char_prop :List of 1
#> $ var_type :List of 1
#> $ group_label : Factor w/ 3 levels "Placebo","Low Dose",..: 1 3 2
#> $ analysis : chr "exp_dur"
#> $ char_stat_groups:List of 5
#> $ char_n_cum :List of 1
#> $ char_prop_cum :List of 1
#> $ char_stat_cums :List of 5
#> $ extend_call :List of 1
all_stats <- bind_rows(outdata$char_stat_groups, .id = "duration_category")
all_stats
#> duration_category name Placebo Low Dose High Dose
#> 1 >=1 day Mean 4.5 4.0 5.0
#> 2 >=1 day SD 2.1 2.4 1.0
#> 3 >=1 day SE 1.5 1.2 0.6
#> 4 >=1 day Median 4.5 4.5 5.0
#> 5 >=1 day Min 3.0 1.0 4.0
#> 6 >=1 day Max 6.0 6.0 6.0
#> 7 >=1 day Q1 to Q3 3.75 to 5.25 2.5 to 6 4.5 to 5.5
#> 8 >=1 day Range 3 to 6 1 to 6 4 to 6
#> 9 >=7 days Mean 17.6 17.8 19.1
#> 10 >=7 days SD 6.0 5.4 6.6
#> 11 >=7 days SE 1.7 1.6 2.2
#> 12 >=7 days Median 21.0 19.0 21.0
#> 13 >=7 days Min 9.0 9.0 8.0
#> 14 >=7 days Max 25.0 25.0 26.0
#> 15 >=7 days Q1 to Q3 13 to 23 14 to 22 15 to 25
#> 16 >=7 days Range 9 to 25 9 to 25 8 to 26
#> 17 >=28 days Mean 55.3 57.2 54.1
#> 18 >=28 days SD 15.1 16.8 16.6
#> 19 >=28 days SE 2.7 3.7 3.2
#> 20 >=28 days Median 54.0 54.5 53.0
#> 21 >=28 days Min 28.0 29.0 29.0
#> 22 >=28 days Max 80.0 82.0 83.0
#> 23 >=28 days Q1 to Q3 44.5 to 67.5 43.75 to 73 40.5 to 68
#> 24 >=28 days Range 28 to 80 29 to 82 29 to 83
#> 25 >=12 weeks Mean 125.4 128.8 126.8
#> 26 >=12 weeks SD 27.5 25.1 25.4
#> 27 >=12 weeks SE 4.4 3.6 3.8
#> 28 >=12 weeks Median 124.0 135.0 126.0
#> 29 >=12 weeks Min 89.0 84.0 84.0
#> 30 >=12 weeks Max 165.0 167.0 167.0
#> 31 >=12 weeks Q1 to Q3 98.5 to 155 108.75 to 150.25 105 to 152
#> 32 >=12 weeks Range 89 to 165 84 to 167 84 to 167
#> 33 >=24 weeks Mean 168.0 <NA> <NA>
#> 34 >=24 weeks SD NA <NA> <NA>
#> 35 >=24 weeks SE NA <NA> <NA>
#> 36 >=24 weeks Median 168.0 <NA> <NA>
#> 37 >=24 weeks Min 168.0 <NA> <NA>
#> 38 >=24 weeks Max 168.0 <NA> <NA>
#> 39 >=24 weeks Q1 to Q3 168 to 168 <NA> <NA>
#> 40 >=24 weeks Range 168 to 168 <NA> <NA>
#> Total var_label
#> 1 4.4 Exposure Duration (Days)
#> 2 1.8 Exposure Duration (Days)
#> 3 0.6 Exposure Duration (Days)
#> 4 5.0 Exposure Duration (Days)
#> 5 1.0 Exposure Duration (Days)
#> 6 6.0 Exposure Duration (Days)
#> 7 3 to 6 Exposure Duration (Days)
#> 8 1 to 6 Exposure Duration (Days)
#> 9 18.1 Exposure Duration (Days)
#> 10 5.8 Exposure Duration (Days)
#> 11 1.0 Exposure Duration (Days)
#> 12 20.0 Exposure Duration (Days)
#> 13 8.0 Exposure Duration (Days)
#> 14 26.0 Exposure Duration (Days)
#> 15 13 to 23 Exposure Duration (Days)
#> 16 8 to 26 Exposure Duration (Days)
#> 17 55.4 Exposure Duration (Days)
#> 18 15.9 Exposure Duration (Days)
#> 19 1.8 Exposure Duration (Days)
#> 20 53.0 Exposure Duration (Days)
#> 21 28.0 Exposure Duration (Days)
#> 22 83.0 Exposure Duration (Days)
#> 23 42 to 70.5 Exposure Duration (Days)
#> 24 28 to 83 Exposure Duration (Days)
#> 25 127.1 Exposure Duration (Days)
#> 26 25.7 Exposure Duration (Days)
#> 27 2.2 Exposure Duration (Days)
#> 28 130.5 Exposure Duration (Days)
#> 29 84.0 Exposure Duration (Days)
#> 30 167.0 Exposure Duration (Days)
#> 31 105 to 152 Exposure Duration (Days)
#> 32 84 to 167 Exposure Duration (Days)
#> 33 168.0 Exposure Duration (Days)
#> 34 NA Exposure Duration (Days)
#> 35 NA Exposure Duration (Days)
#> 36 168.0 Exposure Duration (Days)
#> 37 168.0 Exposure Duration (Days)
#> 38 168.0 Exposure Duration (Days)
#> 39 168 to 168 Exposure Duration (Days)
#> 40 168 to 168 Exposure Duration (Days)
plotly_exp_duration()
The function takes the fully prepared outdata from the above steps to simply visualizes these pre-calculated statistics in an interactive way. It reshapes the counts and proportions tables from wide to long format, so each row corresponds to a specific combination of: Exposure duration category (e.g., >=7 days). Treatment group (e.g., Placebo). It uses these reshaped tables to create stacked bar charts or grouped bar charts that show: The number or proportion of participants in each exposure duration category for each treatment group. It also uses the summary statistics (char_stat_groups) to create hover text that shows detailed statistics for each bar (i.e., for each treatment group × exposure duration category). The interactive dropdown lets you switch between different views (e.g., cumulative exposure duration, exclusive categories, horizontal bars).