Interactive forest plot for clinical trial safety analysis using 'metalite', 'reactable', 'plotly', and Analysis Data Model (ADaM) datasets. Includes functionality for adverse event filtering, incidence-based group filtering, hover-over reveals, and search and sort operations. The workflow allows for metadata construction, data preparation, output formatting, and interactive plot generation.

The easiest way to get forestly is to install from CRAN:
install.packages("forestly")
Alternatively, to use a new feature or get a bug fix, you can install the development version of forestly from GitHub:
# install.packages("remotes")
remotes::install_github("Merck/forestly")
The forestly package creates interactive forest plots for clinical trial analysis & reporting.
We assume ADaM datasets are ready for analysis and leverage metalite data structure to define inputs and outputs.
The general workflow is:
metalite.prepare_ae_forestly() prepares datasets for interactive forest plot.format_ae_forestly() formats output layout.ae_forestly() generates an interactive forest plot.Here is a quick example
library("forestly")
adsl <- forestly_adsl
adae <- forestly_adae
adsl$TRTA <- factor(
adsl$TRT01A,
levels = c("Xanomeline Low Dose", "Placebo"),
labels = c("Low Dose", "Placebo")
)
adae$TRTA <- factor(
adae$TRTA,
levels = c("Xanomeline Low Dose", "Placebo"),
labels = c("Low Dose", "Placebo")
)
analysis_plan <- metalite::plan(
analysis = "ae_forestly",
population = "apat",
observation = "wk12",
parameter = "any;rel;ser"
)
meta <- metalite::meta_adam(population = adsl, observation = adae) |>
metalite::define_plan(plan = analysis_plan) |>
metalite::define_population(
name = "apat",
var = c("USUBJID", "SAFFL", "TRTA", "SITEID", "SEX", "RACE", "AGE"),
group = "TRTA",
subset = SAFFL == "Y",
label = "All Participants as Treated"
) |>
metalite::define_observation(
name = "wk12",
var = c(
"USUBJID", "SAFFL", "TRTA", "SITEID", "SEX", "RACE", "AGE",
"ASTDY", "AEDECOD", "AEBODSYS", "AESER", "AEREL", "AEACN",
"AEOUT", "ADURN", "ADURU"
),
group = "TRTA",
subset = SAFFL == "Y",
label = "Weeks 0 to 12"
) |>
metalite::define_parameter(
name = "any",
term1 = "",
term2 = "",
var = "AEDECOD",
soc = "AEBODSYS",
label = "All AEs"
) |>
metalite::define_parameter(
name = "rel",
term1 = "Drug-Related",
term2 = "",
subset = AEREL %in% c("POSSIBLE", "PROBABLE"),
var = "AEDECOD",
soc = "AEBODSYS",
label = "Drug-related AEs"
) |>
metalite::define_parameter(
name = "ser",
term1 = "Serious",
term2 = "",
subset = AESER == "Y",
var = "AEDECOD",
soc = "AEBODSYS",
label = "Serious AEs"
) |>
metalite::define_analysis(
name = "ae_forestly",
label = "Interactive forest plot"
) |>
metalite::meta_build()
meta |>
prepare_ae_forestly(parameter = "any;rel;ser") |>
format_ae_forestly() |>
ae_forestly()
The interactive features for safety analysis include: