Simulation-Based Power Evaluation for Stepped-Wedge Cluster Randomized Trials

Provides simulation-based power, type I error, and operating- characteristic evaluation for stepped-wedge cluster randomized trials. General binary-outcome designs support arbitrary crossover schedules, unequal clusters per sequence, secular trends, flexible cluster-period sizes, reproducible parallel execution, sensitivity grids, and mixed-model diagnostics. A component-based engine supports the four treatment states Control, A, B, and A+B under arbitrary asynchronous schedules, including structurally unobserved cluster-periods, withdrawal, reintroduction, wash-in delays, user-defined carryover decay, component main effects, an A-by-B interaction, estimability audits, multiplicity adjustment, conditional and failure-aware power, and explicit classification of hard model errors, nonconvergence, non-finite contrasts, singular fits, and successful fits. A batch-aware interface represents classic and batched stepped-wedge designs with delayed cluster initiation, structurally unobserved cluster-periods, and calendar-time, time-on-trial, or separate batch-specific time effects, following Kasza, Bowden, Hooper and Forbes (2022) . The cumulative Control-to-A-to-A+B interface from earlier versions remains available. The design and mixed-effects analysis follow Hussey and Hughes (2007) . Intraclass correlations for binary outcomes are converted to random-intercept standard deviations on the latent scale of the logistic-normal model, as reviewed by Eldridge, Ukoumunne and Carlin (2009) . Monte Carlo uncertainty is reported using exact intervals from Clopper and Pearson (1934) .


stepwedgepower

CRAN status R-CMD-check

stepwedgepower provides simulation-based design evaluation for stepped-wedge cluster randomized trials with aggregated binary outcomes. It connects the rollout schedule, data-generating assumptions, planned mixed model, and empirical operating characteristics in one reproducible workflow.

Version 0.4.1 supports:

  • arbitrary binary stepped-wedge crossover schedules;
  • unequal clusters per sequence and flexible cluster-period sizes;
  • secular trends and latent-scale ICC input;
  • empirical power, type I error, bias, coverage, convergence, singularity, and Monte Carlo uncertainty;
  • explicit fit-outcome diagnostics separating hard GLMM errors, nonconverged fits, converged fits with non-finite contrasts, singular fits, and successful fits;
  • classic and batched stepped-wedge designs with delayed cluster initiation, structurally unobserved cluster-periods, and explicit batch metadata;
  • calendar-time, time-on-trial, and separate batch-specific time models for simulation, analysis, auditing, power, and type I error evaluation;
  • sensitivity grids and reproducible parallel simulation;
  • asynchronous cumulative schedules in which clusters move from Control to A and later add B at different times;
  • separate A, incremental-B, and total A+B contrasts, multiplicity adjustment, schedule auditing, conditional power, and failure-aware power;
  • a general component engine for Control, A, B, and A+B, including arbitrary withdrawal and reintroduction schedules;
  • structurally incomplete and batched stepped-wedge schedules in which dashes or missing cells contribute no cluster-period outcome;
  • separate wash-in, restart, and carryover rules for A and B, together with an optional A-by-B interaction;
  • standard factorial contrasts, formal estimability checks, and comparisons of multiple candidate schedules.

Installation

install.packages("stepwedgepower")

Install the development version from GitHub with:

# install.packages("remotes")
remotes::install_github("AmandaLinLi/stepwedgepower")

Standard stepped-wedge workflow

library(stepwedgepower)

design <- sw_design(
  clusters_per_sequence = c(8, 8, 8, 8),
  crossover_period = c(2, 3, 4, 5),
  n_periods = 5
)

assumptions <- sw_assumptions(
  baseline_prob = 0.10,
  treatment_or = 1.50,
  icc = 0.05,
  period_effects = c(0, 0.05, 0.10, 0.15, 0.20),
  n_per_cluster_period = 30
)

trial <- simulate_swcrt(design, assumptions, seed = 1)
fit <- analyze_swcrt(trial)

# Use substantially more simulations for a final design decision.
power <- power_swcrt(design, assumptions, nsim = 500, seed = 2026)
summary(power)

General Control, A, B, and A+B design

Version 0.4.1 accepts arbitrary four-state schedules. In this example, some sequences follow Control -> A -> A+B -> B, so A is withdrawn and its effect is allowed to decay over two periods. Other sequences begin with B before adding A.

state <- rbind(
  S1 = c(0, 0, 1, 1, 3, 3, 2, 2),
  S2 = c(0, 0, 0, 1, 1, 3, 3, 2),
  S3 = c(0, 0, 2, 2, 3, 3, 3, 3),
  S4 = c(0, 0, 0, 2, 2, 3, 3, 3),
  S5 = c(0, 0, 1, 1, 1, 3, 3, 3),
  S6 = c(0, 0, 2, 2, 2, 3, 3, 3)
)

component_design <- sw_component_design(
  clusters_per_sequence = rep(5, 6),
  state = state
)

component_assumptions <- sw_component_assumptions(
  baseline_prob = 0.15,
  treatment_or_a = 1.35,
  treatment_or_b = 1.25,
  interaction_or = 1.10,
  delay_a = 1,
  delay_b = 1,
  carryover_periods_a = 2,
  carryover_weights_a = c(0.50, 0.25),
  restart_rule_a = "reset",
  interaction_mode = "effective_overlap",
  icc = 0.05,
  period_effects = log(seq(1.00, 1.08, length.out = 8)),
  n_per_cluster_period = 25
)

audit_component_design(component_design, component_assumptions)

one_trial <- simulate_component_swcrt(
  component_design, component_assumptions, seed = 123
)
fit <- fit_component_model(one_trial, multiplicity = "holm")
fit$contrasts

# Use at least several thousand simulations for a manuscript analysis.
# component_power <- power_component_swcrt(
#   component_design, component_assumptions,
#   nsim = 5000, multiplicity = "holm", n_cores = 4, seed = 2026
# )
# summary(component_power)
# component_power$fit_diagnostics
# subset(
#   component_power$replicate_diagnostics,
#   fit_status != "successful_fit" | singular_fit
# )

fit_diagnostics summarizes the primary mutually exclusive analysis outcomes: hard GLMM error, nonconverged fit, converged fit with a non-finite requested contrast, and successful fit. singular_fit is reported as a separate, non-exclusive property because a singular model may still converge and return finite contrasts.

The standard contrasts are A versus Control, B versus Control, B versus A, A+B versus Control, A+B versus A, A+B versus B, and the A-by-B interaction. When a component is withdrawn, carryover weights are applied to its log-odds effect. The interaction can either follow overlap of the effective component weights or require both components to remain currently assigned.

The installed demonstration is available at:

system.file("examples", "demo_component_four_state.R", package = "stepwedgepower")

Classic SWD and batched stepped-wedge designs

A batched stepped-wedge design (BSWD) allows clusters to begin trial participation in batches with staggered starts. A dash denotes a structurally unobserved clinic-period and is never recoded as Control. Version 0.4.1 stores calendar period and relative time since batch initiation; batch labels may be supplied directly or inferred from first observed periods.

swd <- sw_batched_design(
  clusters_per_sequence = c(5, 5),
  state = rbind(
    `Group 1` = c("0", "1", "1+2", "1+2"),
    `Group 2` = c("0", "0", "1", "1+2")
  ),
  batch = c("Batch 1", "Batch 1")
)

bswd <- sw_batched_design(
  clusters_per_sequence = c(2, 2, 3, 3),
  state = rbind(
    `Group 1` = c("0", "1", "1+2", "1+2", "-"),
    `Group 2` = c("0", "0", "1", "1+2", "-"),
    `Group 3` = c("-", "0", "1", "1+2", "1+2"),
    `Group 4` = c("-", "0", "0", "1", "1+2")
  ),
  batch = c("Batch 1", "Batch 1", "Batch 2", "Batch 2")
)

batched_assumptions <- sw_batched_assumptions(
  baseline_prob = 0.15,
  treatment_or_a = 1.35,
  treatment_or_b = 1.25,
  interaction_mode = "none",
  icc = 0.05,
  n_per_cluster_period = 25,
  time_model = "calendar",
  time_effects = log(seq(1.00, 1.08, length.out = 5))
)

component_resource_summary(swd, batched_assumptions)
component_resource_summary(bswd, batched_assumptions)
# Both designs have 40 observed clinic-periods and 1,000 observations.

The BSWD interface supports calendar time, shared time on trial, and separate batch-specific time. It can compare designs under equal resources and can fit a different time model from the one used to generate data.

contrasts <- c("A_vs_control", "AB_vs_A", "AB_vs_control")

audit_batched_design(
  bswd, batched_assumptions,
  time_model = "separate",
  contrasts = contrasts,
  include_interaction = FALSE
)

# comparison <- compare_swd_bswd(
#   swd, bswd, batched_assumptions,
#   nsim = 5000, contrasts = contrasts,
#   include_interaction = FALSE, multiplicity = "holm",
#   n_cores = 4, seed = 2026
# )

The installed demonstration is available at:

system.file("examples", "demo_batched_SWD_BSWD.R", package = "stepwedgepower")

Asynchronous Control to A to A+B design

The cumulative extension treats B as an add-on intervention: B is never observed without A, so its coefficient is the incremental effect of A+B versus A.

three_state <- sw_multistage_design(
  clusters_per_sequence = rep(6, 8),
  a_start = c(2, 3, 4, 5, 6, 7, 8, 9),
  b_start = c(6, 8, 7, 10, 9, 11, 12, 12),
  n_periods = 12,
  sequence_names = paste0("S", 1:8)
)

multistage_assumptions <- sw_multistage_assumptions(
  baseline_prob = 0.15,
  treatment_or_a = 1.40,
  incremental_or_b = 1.30,
  delay_a = 1,
  delay_b = 1,
  icc = 0.05,
  n_per_cluster_period = 30
)

audit_multistage_design(
  three_state,
  delay_a = multistage_assumptions$delay_a,
  delay_b = multistage_assumptions$delay_b
)

# power_ab <- power_multistage_swcrt(
#   three_state, multistage_assumptions,
#   nsim = 5000, multiplicity = "holm", n_cores = 4, seed = 2026
# )
# summary(power_ab)

To compare the same A rollout with and without B:

two_state <- sw_multistage_design(
  clusters_per_sequence = three_state$clusters_per_sequence,
  a_start = three_state$a_start,
  b_start = rep(Inf, three_state$n_sequences),
  n_periods = three_state$n_periods,
  sequence_names = three_state$sequence_names
)

# comparison <- compare_multistage_designs(
#   two_state, three_state, multistage_assumptions,
#   nsim = 5000, multiplicity = "holm", n_cores = 4, seed = 2026
# )
# comparison

The installed demonstration is available at:

system.file("examples", "demo_async_A_AB.R", package = "stepwedgepower")

Manuscript benchmark and validation suite

Version 0.4.1 includes a non-exported reproducibility module under inst/benchmarks/. It covers the software comparison in Table 2, the calendar-time delay curves in Figure 3, the separate-time GEE grid in Table 3, and the limited-cluster variance curves in Figure 5 of Lin et al. (2026). Reference values, source notes, tolerances, package versions, and session information are saved with the results.

benchmark_dir <- system.file("benchmarks", package = "stepwedgepower")

Sys.setenv(
  STEPWEDGEPOWER_RUN_EXTERNAL = "true",
  STEPWEDGEPOWER_BENCHMARK_STRICT = "true",
  STEPWEDGEPOWER_BENCHMARK_OUTPUT =
    file.path(getwd(), "stepwedgepower-benchmark-results")
)

source(file.path(benchmark_dir, "run_all.R"))

swCRTdesign and swdpwr are optional and are used only for the external Table 2 and Table 3 comparisons. Figure 3 uses an independent base-R matrix calculation. Figure 5 is checked both from the Appendix C closed forms and by independent WLS matrix inversion. None of the benchmark helpers is exported.

Vignettes

vignette("stepped-wedge-design", package = "stepwedgepower")
vignette("component-four-state", package = "stepwedgepower")
vignette("batched-stepped-wedge-designs", package = "stepwedgepower")
vignette("asynchronous-a-ab", package = "stepwedgepower")
vignette("lpa-case-study", package = "stepwedgepower")
vignette("benchmark-validation", package = "stepwedgepower")

The Lp(a) functions are retained as application wrappers over the package's generic clustered-data tools; the core simulation and power interfaces are application-neutral.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("stepwedgepower")

0.4.1 by Lin (Amanda) Li, 7 hours ago


https://github.com/AmandaLinLi/stepwedgepower


Report a bug at https://github.com/AmandaLinLi/stepwedgepower/issues


Browse source code at https://github.com/cran/stepwedgepower


Authors: Lin (Amanda) Li [aut, cre] , Florin Vaida [aut] (degree: PhD)


Documentation:   PDF Manual  


MIT + file LICENSE license


Imports lme4, lifecycle, graphics, grDevices, stats, parallel, utils

Suggests testthat, knitr, rmarkdown, swCRTdesign, swdpwr


See at CRAN