The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
This vignette provides an high-level illustration of ANCOVA
with combined treatment groups in junco.
The main purpose is to highlight the ability to construct tables with
combined groups using junco function
a_summarize_ancova_j().
The various options such as weighting strategies, interaction models,
and alternative estimands will be described.
ANCOVA is commonly used for covariate-adjusted analyses of change from baseline in clinical trials. Regulatory tables often require pooling of treatment arms while preserving the original estimand.
The dataset used as an example is a small dataset with simulated
values for BASE and CHG.
library(dplyr)
library(rtables)
#> Warning: package 'rtables' was built under R version 4.5.2
#> Warning: package 'formatters' was built under R version 4.5.2
library(junco)
set.seed(101)
adchg <- tibble(
USUBJID = sprintf("SUBJ-%03d", 1:300),
TRT01A = factor(rep(c("Placebo", "Low Dose", "High Dose"), length.out = 300)),
REGION = factor(sample(c("EU", "US"), 300, replace = TRUE, prob = c(0.6, 0.4))),
BASE = rnorm(300, 50, 10),
CHG = rnorm(300, 0, 8)
)A combined treatment column can be added in an rtables
layout, by utilizing a combodf dataframe.
As seen further in this document, adding
split_fun = add_combo_levels(combodf) in
split_cols_by call, will result in a combined treatment
column in the final table.
The ANCOVA model used here is:
CHG ~ TRT01A + BASE + REGION
The model is fitted once using the original randomized treatment variable, for all columns, including the combined column.
The recommended approach for dealing with a combined treatment group
column in an ANCOVA table, is to derive the estimates for that column as
contrasts (least-squares means) from the linear ANCOVA model.
This can be achieved by specifying the argument
method_combo = "contrasts".
lyt <- basic_table() |>
split_cols_by(
"TRT01A",
ref_group = "Placebo",
split_fun = add_combo_levels(combodf)
) %>%
add_colcounts() |>
analyze(
vars = "CHG",
afun = a_summarize_ancova_j,
var_labels = "Change from Baseline",
extra_args = list(
variables = list(arm = "TRT01A", covariates = c("BASE", "REGION")),
ref_path = c("TRT01A", "Placebo"),
method_combo = "contrasts",
weights_combo = "equal",
weights_emmeans = "equal",
conf_level = 0.95
)
)
build_table(lyt, adchg)
#> High Dose Low Dose Placebo Active
#> (N=100) (N=100) (N=100) (N=200)
#> —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#> n 100 100 100 200
#> Mean (SD) -0.76 (7.541) -0.12 (7.490) -1.16 (6.510) -0.44 (7.504)
#> Median -0.27 -0.13 -1.60 -0.18
#> Min, max -22.1, 16.8 -15.2, 15.6 -16.2, 17.8 -22.1, 16.8
#> 25% and 75%-ile -6.51, 4.08 -5.82, 4.25 -5.68, 2.48 -6.44, 4.15
#> Adjusted Mean (SE) -0.73 (0.72) -0.03 (0.72) -0.97 (0.73) -0.38 (0.51)
#> Adjusted Mean (95% CI) -0.73 (-2.15, 0.68) -0.03 (-1.45, 1.40) -0.97 (-2.41, 0.47) -0.38 (-1.38, 0.63)
#> Difference in Adjusted Means (95% CI) 0.24 (-1.78, 2.26) 0.95 (-1.06, 2.95) 0.59 (-1.15, 2.34)
#> p-value 0.815 0.354 0.504Note the argument weights_combo in the above layout
definition. When defining contrasts in a linear model, weights can
specified to use in averaging predictions. See
?emmeans::emmeans() for more details.
The following 3 weight scenarios are available for
weights_combo:
equal: equal contribution of armsproportional: weighted by observed sample sizeproportional_marginal: marginal weights across
interaction strataIf no interaction term is included in the model, the choices
proportional and proportional_marginal lead to
the same weights (by observed sample size), reducing to 2 options
only.
While, if an interaction, for example a term like
TRT01A * REGION is included, proportional and
proportional_marginal are slightly different, with
proportional according to the proportions observed in the
interaction strata.
The option method_combo = "collapse" is available as
alternative approach, mainly as a quick verification method, and for
consistency reason with another internal system.
In this scenario, the ANCOVA model is re-fitted on pooled arms and as
such changes the estimand.
While it is available as an option, our recommendation is to use the
contrasts approach, and only utilize
method_combo = "collapse" when explicitly specified in the
SAP.
method_combo = "contrasts" approach is aligned with
emmeans theorySee also [junco::a_summarize_ancova_j()].
Let:
All quantities are obtained from the fitted ANCOVA model.
A combined treatment LS mean for a set of arms \(C\) is defined as:
\[ \hat{\mu}_{C} = \sum_{k \in C} w_k \, \hat{\mu}_k , \qquad \sum_{k \in C} w_k = 1 \]
where \(w_k\) are user-specified weights (e.g. equal or proportional).
The variance of the combined LS mean is:
\[ \mathrm{Var}(\hat{\mu}_{C}) = \mathbf{w}^T \, \mathbf{V} \, \mathbf{w} \]
This corresponds exactly to a linear contrast implemented via
emmeans::contrast().
The estimated difference between two individual treatment arms \(k\) and \(r\) (e.g. Active vs Placebo) is defined as the contrast:
\[ \hat{\delta}_{k,r} = \hat{\mu}_k - \hat{\mu}_r \]
with variance:
\[ \mathrm{Var}(\hat{\delta}_{k,r}) = \mathrm{Var}(\hat{\mu}_k) + \mathrm{Var}(\hat{\mu}_r) - 2 \, \mathrm{Cov}(\hat{\mu}_k, \hat{\mu}_r) \]
This covariance term is automatically accounted for when contrasts are derived from the joint covariance matrix \(\mathbf{V}\).
For a combined treatment \(C\) compared to reference arm \(r\):
\[ \hat{\delta}_{C,r} = \hat{\mu}_{C} - \hat{\mu}_r \]
This can be written as a single linear contrast with weight vector:
\[ \mathbf{w}_{C,r} = (w_1, \ldots, w_K, -1) \]
and variance:
\[ \mathrm{Var}(\hat{\delta}_{C,r}) = \mathbf{w}_{C,r}^T \, \mathbf{V} \, \mathbf{w}_{C,r} \]
This ensures internally consistent standard errors, confidence intervals, and p-values for combined treatment comparisons.
When the ANCOVA model includes interaction terms
(e.g. TRT01A * REGION), LS means are estimated
within each interaction stratum.
In this setting:
Formally, the combined LS mean marginal over strata is:
\[ \hat{\mu}_{C} = \sum_{s} \pi_s \, \Big( \sum_{k \in C} w_{k|s} \, \hat{\mu}_{k,s} \Big) \]
where:
The distinction between weights_combo = "proportional"
and "proportional_marginal" determines whether \(w_{k|s}\) or \(\pi_s\) reflect observed sample sizes
within or across strata.
This two-stage weighting clarifies how estimands change in the presence of interactions and avoids implicit, undocumented averaging.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.