Every counted refit is scored against the pre-specified result:
The verdict then reads:
Marginal is a separate flag on the pre-specified p-value: it is set when p lies within a band around alpha (the default band is alpha/2 to 2 alpha). A marginal result is expected to be sensitive, because a p-value near 0.05 crosses 0.05 under small perturbations whatever the true effect. That is the point of keeping the two apart: “sensitive and marginal” says the trial was sized so that its p-value landed near alpha, “fragile” says the conclusion depends on a decision.
ICH E9(R1) distinguishes sensitivity analyses, which keep the
estimand and vary an assumption or a modelling choice, from
supplementary analyses, which target a different estimand. Every row
carries a role. Model families (covariance, inference,
covariates, weighting, estimator class), deletions, re-randomisation and
the imputation families are sensitivity analyses; alternative data sets,
populations, other visits and intercurrent-event strategies default to
supplementary. The verdict is reported over all counted rows and over
the sensitivity rows alone.
Rows that reproduce the pre-specified analysis exactly are not counted. A specification reached by two families (the unstructured covariance appears in the covariance panel and in a grid, say) is counted once. Tipping-point grids are searches, not alternatives; the delta-zero multiple-imputation row is an alternative. Deletions are counted but summarised separately from alternative analyses, because their number is a property of the sample size, not of the analyst’s choices.
stress_calibrate() simulates trials from a planned
design and runs a light stress test on each. The pattern it produces,
and which the methods paper reports in full, is:
A small run (the vignette keeps it to a few trials) looks like this:
library(ballast)
stress_calibrate(n_per_arm = 30, power = c(0, 0.8), n_trials = 3, seed = 1)
#> Stress-test calibration: 30 per arm, 4 visits, SD 10, AR(1) 0.6, dropout 0.08 per visit
#> power_target delta trials power_observed marginal robust sensitive fragile
#> 0.0 0.00 3 0.000 0 0.667 0.333 0
#> 0.8 7.33 3 0.333 0 0.667 0.333 0
#> sensitive_given_sig fragile_k1_given_sig
#> NA NA
#> 1 NAstress_fragility() is a greedy forward search for the
smallest set of subjects whose removal changes significance, leaves the
pre-specified interval, or reverses the direction. The number of steps
is an analogue of the fragility index for a continuous longitudinal
endpoint, with two differences: the unit is a participant, not an event,
and the target can be the interval or the direction, which separates
“loses significance” from “changes conclusion”. Because the search is
greedy the count is an upper bound on the true minimum, and the subjects
it names are a diagnostic, not a verdict on them.
stress_explain() takes one row of the census and
attributes the difference between its estimate and the pre-specified
estimate to subjects, by comparing each subject’s leave-one-out
influence under the two specifications. Use it on the rows that crossed
alpha before writing the interpretation.