goldilocks can analyze completed binary endpoints using
method = "bayes-bin". This is useful when the final
decision is based on the event indicator by a fixed endpoint time,
rather than the event time itself. The trial simulator still uses
time-to-event hazards to model not-yet-observed outcomes at interim
looks, but it can either impute a future event time or draw the binary
endpoint status directly. The final analysis reduces each completed
dataset to binary event status by end_of_study.
Two distinct kinds of prior can therefore enter a Bayesian binary
design. prior_surv is the Gamma prior on
piecewise-exponential hazards used for interim predictive imputation,
and prior_surv_final optionally overrides it for final
imputation. prior_bin is the Beta prior on the binary
endpoint event probability in each arm and is used to analyze every
completed or imputed dataset. Thus, interim predictive probabilities are
affected by prior_surv and prior_bin; a final
imputed analysis uses prior_surv_final and
prior_bin; and a non-imputed final binary analysis is
affected by prior_bin alone.
The imputation and completed-data analysis are separate models. The
piecewise-exponential Gamma model uses event times and available
event-free follow-up to predict pending endpoint statuses. The
beta-binomial model then analyzes the completed event indicators at
end_of_study. prior_bin is not derived from
the binary-horizon distribution implied by prior_surv, and
goldilocks does not treat the two stages as one joint
Bayesian model. This modular combination may be intentional, but its
operating characteristics can depend on both prior specifications
whenever outcomes require imputation. Choosing
binary_imputation = "bernoulli" rather than
"event-time" does not remove the distinction: both options
use the same piecewise-exponential prediction model.
The saved analysis specification records prior_surv,
prior_surv_final, prior_bin, and
end_of_study, together with the Gamma prior parameters by
analysis stage, arm, and interval. These values should be included in
the simulation report because both prior families can affect interim
decisions.
For the examples below, we use the default weakly informative \operatorname{Gamma}(0.1, 0.1) hazard prior and a uniform \operatorname{Beta}(1, 1) binary-endpoint prior:
hazard_prior <- c(0.1, 0.1) # Gamma shape and rate for predictive imputation
prior_bin <- c(1, 1) # Beta shapes for the binary endpoint analysisTwo practical consequences follow:
-
method = "bayes-bin"only supports one-sided alternatives:alternative = "less"oralternative = "greater". - The final binary analysis requires complete endpoint status.
Subjects who are censored before
end_of_studymust be imputed (imputed_final = TRUE) or, ifimputed_final = FALSE, excluded from the final binary analysis.
The examples use prop_loss = 0. If dropout is added,
prop_loss specifies the CDF of an independent exponential
dropout time at end_of_study, not an exact fraction of
missing binary outcomes. Events occurring before dropout remain
observed. Consequently, excluding early-censored subjects can bias
binary event probabilities even though censoring is independent for
survival analysis. Assess final imputation and its event-time-model
assumptions when evaluating binary designs with dropout.
Two-arm design
Suppose the control event probability by 12 months is 35%, and the
treatment is expected to reduce this to 25%. We use a beta-binomial
final analysis with a uniform \operatorname{Beta}(1, 1) prior in each arm.
Since lower event probability is beneficial, we use
alternative = "less" and compare the posterior distribution
of
p_{\text{treatment}} - p_{\text{control}}
against h0 = 0.
end_of_study <- 12
hc <- prop_to_haz(0.35, endtime = end_of_study)
ht <- prop_to_haz(0.25, endtime = end_of_study)
two_arm_args <- list(
hazard_treatment = ht,
hazard_control = hc,
cutpoints = NULL,
N_total = 120,
lambda = 10,
lambda_time = NULL,
interim_look = 80,
end_of_study = end_of_study,
prior_surv = hazard_prior,
prior_bin = prior_bin,
bin_method = "quadrature",
block = 2,
rand_ratio = c(control = 1, treatment = 1),
prop_loss = 0,
alternative = "less",
h0 = 0,
Fn = 0.05,
Sn = 0.90,
prob_ha = 0.95,
N_impute = 20,
method = "bayes-bin",
imputed_final = FALSE
)
out_two_arm <- do.call(survival_adapt, two_arm_args)
out_two_arm
#> prob_threshold margin alternative N_treatment N_control N_enrolled N_max
#> 1 0.95 0 less 60 60 120 120
#> post_prob_ha est_final ppp_success stop_futility stop_immediate_success
#> 1 0.9178978 -0.1129032 0.85 0 0
#> stop_expected_success trial_success stopping_reason decision_time
#> 1 0 FALSE maximum_sample_size 22.911
#> accrual_stop_time analysis_ready_time planned_completion_time
#> 1 10.911 22.911 22.911
#> followup_person_time peak_active_followup
#> 1 1193.166 106For method = "bayes-bin", est_final is the
posterior mean binary effect: the treatment event probability minus the
control event probability. post_prob_ha is the posterior
probability that this difference is below h0 when
alternative = "less".
Choosing the binary imputation approach
The default binary_imputation = "event-time" approach
samples a future event time from the piecewise-exponential model,
conditional on the subject remaining event-free through the available
follow-up time T. The sampled time is
then converted to event or no event at the endpoint T^*.
With binary_imputation = "bernoulli", the package skips
the unused event time and calculates the endpoint probability
directly:
\begin{aligned} p &= \Pr(T_{\text{event}} \leq T^* \mid T_{\text{event}} > T) \\ &= \frac{S(T) - S(T^*)}{S(T)} \\ &= 1 - \exp\left\{-[H(T^*) - H(T)]\right\}. \end{aligned}
It then draws X \sim \operatorname{Bernoulli}(p). For subjects who are not yet enrolled, T=0. Observed events are not imputed. Each completed dataset still uses a sampled posterior hazard, so both approaches retain uncertainty in the predictive piecewise-exponential model.
The two approaches imply the same endpoint distribution. Finite Monte Carlo estimates can nevertheless differ, so comparisons should use adequate numbers of trials and imputations. The following small comparison uses a common seed to make the numerical results reproducible:
compare_binary_imputation <- function(imputation) {
set.seed(2101)
fit <- do.call(
survival_adapt,
c(two_arm_args, list(binary_imputation = imputation))
)
fit[c("ppp_success", "post_prob_ha", "est_final")]
}
rbind(
`conditional event time` = compare_binary_imputation("event-time"),
`direct Bernoulli status` = compare_binary_imputation("bernoulli")
)
#> ppp_success post_prob_ha est_final
#> conditional event time 0 0.4042967 0.02380952
#> direct Bernoulli status 0 0.4042967 0.02380952The direct Bernoulli calculation can also be more numerically stable for very small survival probabilities because it works from the remaining cumulative hazard rather than subtracting two nearly zero survival probabilities.
Whichever imputation approach is selected, the completed
beta-binomial analysis depends only on the event count and denominator
in each arm. With bin_method = "mc", each predictive
replicate receives an independent set of N_mcmc
beta-posterior draws. Thus, the number of predictive imputations and the
number of posterior draws represent distinct sources of Monte Carlo
error.
Single-arm design
For a single-arm design, set hazard_control = NULL. The
comparator is an external benchmark event probability supplied through
h0, often called a performance goal (PG) or objective
performance criterion (OPC).
Here the benchmark event probability is 30%, and the target event
probability is 20%. With alternative = "less", success
means the posterior probability that the event probability is below 30%
exceeds prob_ha.
benchmark <- 0.30
target <- 0.20
ht_single <- prop_to_haz(target, endtime = end_of_study)
out_single_arm <- survival_adapt(
hazard_treatment = ht_single,
hazard_control = NULL,
cutpoints = NULL,
N_total = 80,
lambda = 8,
lambda_time = NULL,
interim_look = 50,
end_of_study = end_of_study,
prior_surv = hazard_prior,
prior_bin = prior_bin,
bin_method = "quadrature",
prop_loss = 0,
alternative = "less",
h0 = benchmark,
Fn = 0.05,
Sn = 0.90,
prob_ha = 0.95,
N_impute = 20,
method = "bayes-bin",
imputed_final = FALSE
)
out_single_arm
#> prob_threshold margin alternative N_treatment N_control N_enrolled N_max
#> 1 0.95 0.3 less 50 0 50 80
#> post_prob_ha est_final ppp_success stop_futility stop_immediate_success
#> 1 0.9980375 0.1346154 1 0 0
#> stop_expected_success trial_success stopping_reason decision_time
#> 1 1 TRUE expected_success 17.96506
#> accrual_stop_time analysis_ready_time planned_completion_time
#> 1 5.96506 17.96506 17.96506
#> followup_person_time peak_active_followup
#> 1 564.1026 49In this setting est_final is the posterior mean event
probability in the single arm, and post_prob_ha is the
posterior probability that this event probability is below the
benchmark.
Choosing bin_method
The posterior probability can be calculated in three ways:
-
bin_method = "mc"draws from the beta posterior directly. UseN_mcmcto control the number of Monte Carlo draws. -
bin_method = "normal"approximates the posterior event probability or treatment-control difference by a normal distribution with matching mean and variance. -
bin_method = "quadrature"uses numerical integration for the two-arm posterior difference, and the closed-form beta CDF for single-arm designs.
The Monte Carlo method has simulation error, controlled by
N_mcmc. Quadrature is deterministic (up to numerical
integration for a two-arm design) and is a useful high-accuracy default
when it is computationally feasible. The normal approximation is fastest
in a representative two-arm benchmark, but should be used with care when
sample sizes are small or event probabilities are near 0 or 1.
Approximation error can move the posterior probability across
prob_ha, changing success and interim stopping decisions.
Increasing N_mcmc does not correct normal-approximation
error. Use bin_method = "quadrature" or sufficiently
precise Monte Carlo Beta draws when the approximation is unsuitable.
Operating characteristics
As with the survival methods, operating characteristics should be
evaluated by simulation under clinically relevant null and alternative
scenarios. The seed argument makes the Monte Carlo study
reproducible, including when ncores is greater than 1.
out_power <- sim_trials(
N_trials = 1000,
hazard_treatment = ht,
hazard_control = hc,
cutpoints = NULL,
N_total = 120,
lambda = 10,
lambda_time = NULL,
interim_look = 80,
end_of_study = end_of_study,
prior_surv = hazard_prior,
prior_bin = prior_bin,
bin_method = "quadrature",
block = 2,
rand_ratio = c(control = 1, treatment = 1),
prop_loss = 0,
alternative = "less",
h0 = 0,
Fn = 0.05,
Sn = 0.90,
prob_ha = 0.95,
N_impute = 20,
method = "bayes-bin",
imputed_final = FALSE,
return_trace = TRUE,
ncores = 2,
seed = 5107
)
out_null <- update(out_power, hazard_treatment = hc, seed = 5108)
oc <- summarise_sims(list(
"target: treatment event probability 25%" = out_power,
"null: treatment event probability 35%" = out_null
))
effect_by_scenario <- c(
"target: treatment event probability 25%" = 0.25,
"null: treatment event probability 35%" = 0.35
)
oc$true_treatment_event_probability <- unname(effect_by_scenario[oc$scenario])
oc
plot_sim_ocs(
oc,
effect = "true_treatment_event_probability",
xlab = "True treatment event probability"
)
plot_sim_stopping(out_power)
plot_sim_decisions(out_power)These plots separate three complementary questions: how operating
characteristics change with the true binary event probability, where
enrollment stops within one scenario, and how the pair of predictive
probabilities drives each interim decision. Set
return_trace = TRUE only for scenarios where the decision
map is needed; it does not change the estimated operating
characteristics.
The binary endpoint model is still calibrated through the event-time
simulator. When the binary endpoint corresponds to event status by
end_of_study, choose hazards that reproduce clinically
meaningful endpoint probabilities through prop_to_haz() and
ppwe().