Interpreting the verdict

Definitions

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.

Sensitivity versus supplementary

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.

The counting rule

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.

What the simulation shows

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                   NA

Explaining a crossing

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.