This vignette describes the analysis of a proof-of-concept (PoC)
study with one normally distributed endpoint.
vignette("overview") introduces the decision criteria.
Model
In group
(),
the outcomes follow
,
and the data are summarized by the number of subjects
,
the sample mean
and the sample standard deviation
(data_continuous()). The treatment effect is
.
With the Normal-Inverse-chi-squared prior (prior_nix()),
the posterior distribution has the same form with parameters
,
,
and
,
and the posterior distribution of the mean is the t distribution
.
With the vague prior
(prior_vague()), it is
.
For the predictive criterion, the mean of future subjects of a group has the posterior predictive distribution Version 0.1.0 of the package used the squared scale , which treats the future subjects as independent draws from the predictive distribution of one subject and understates the uncertainty.
The posterior and predictive probabilities of the Go and NoGo regions
are probabilities of the difference of two t variables, computed by
ptdiff() with one of three methods (argument
method of design_continuous()):
-
"NI"(the default): numerical integration over the whole real line, exact up to a small numerical error; -
"MM": the moment-matching approximation of the difference by a single t distribution (Yamaguchi, Homma, Takeda and Maruo, submitted), which requires more than 4 degrees of freedom in both groups; -
"MC": Monte Carlo simulation withnMCdraws.
Decision for observed data
A study with 12 subjects in each group and vague priors, with and :
crit <- criterion_posterior(theta_tv = 15, theta_mav = 5,
gamma_go = 0.6, gamma_nogo = 0.7)
des <- design_continuous(n_t = 12, n_c = 12, prior_t = prior_vague(),
prior_c = prior_vague(), criterion = crit)
dec <- qdm_decide(des, data_t = data_continuous(n = 12, mean = 22, sd = 25),
data_c = data_continuous(n = 12, mean = 2, sd = 25))
dec
#> Decision: Go
#> Go: P(theta > 15 | data) = 0.6778 (threshold 0.6, met)
#> NoGo: P(theta <= 5 | data) = 0.08784 (threshold 0.7, not met)
#> Posterior distributions
#> Treatment: mean ~ t(df = 11, location = 22, scale = 7.217)
#> Control: mean ~ t(df = 11, location = 2, scale = 7.217)The posterior distribution of each mean is
.
The three methods of ptdiff() give similar probabilities of
the Go region:
post_t <- dec$posterior_t
post_c <- dec$posterior_c
scale_t <- post_t[["sigma"]] / sqrt(post_t[["kappa"]])
scale_c <- post_c[["sigma"]] / sqrt(post_c[["kappa"]])
set.seed(1)
sapply(c("NI", "MM", "MC"), function(m) {
ptdiff(15, mu_t = post_t[["mu"]], scale_t = scale_t, df_t = post_t[["nu"]],
mu_c = post_c[["mu"]], scale_c = scale_c, df_c = post_c[["nu"]],
method = m, lower.tail = FALSE)
})
#> NI MM MC
#> 0.6777935 0.6780038 0.6791000Prior distributions and external data
An informative Normal-Inverse-chi-squared prior is given by its parameters; for example, a control prior centered at 0 with the weight of 2 subjects for the mean and 4 degrees of freedom for the variance:
des_nix <- design_continuous(
n_t = 12, n_c = 12, prior_t = prior_vague(),
prior_c = prior_nix(mu0 = 0, kappa0 = 2, nu0 = 4, sigma0 = 25),
criterion = crit
)
qdm_decide(des_nix, data_t = data_continuous(12, 22, 25),
data_c = data_continuous(12, 2, 25))$posterior_c
#> mu kappa nu sigma
#> 1.714286 14.000000 16.000000 24.214997External data enter through a power prior with weight : data with subjects, mean and standard deviation act as subjects with the same mean and the sum of squares , which keeps the posterior distribution in closed form (Huang et al., submitted). With the vague prior, the posterior distribution of the mean then has degrees of freedom. Borrowing half of 30 external control subjects:
des_ext <- design_continuous(
n_t = 12, n_c = 12, prior_t = prior_vague(), prior_c = prior_vague(),
criterion = crit,
external_c = borrow(data_continuous(n = 30, mean = 0, sd = 25), a0 = 0.5)
)
dec_ext <- qdm_decide(des_ext, data_t = data_continuous(12, 22, 25),
data_c = data_continuous(12, 2, 25))
dec_ext$posterior_c
#> mu kappa nu sigma
#> 0.8888889 27.0000000 26.0000000 24.7791527The control mean now has 26 degrees of freedom (), and the probability of the Go region is 0.75 (without the external data, 0.678).
Hypothetical control
For an uncontrolled study, Kang, Yamaguchi and Han (2026, Section
4.2.4) give the control mean the same t distribution as the posterior
distribution of the treatment mean, with location
and the squared scale multiplied by
:
The prior of the control group is then not used and is left
NULL:
des_hyp <- design_continuous(
n_t = 12, n_c = 0, prior_t = prior_vague(), criterion = crit,
hypothetical_c = hypothetical(mean = 0, r = 1)
)
qdm_decide(des_hyp, data_t = data_continuous(12, 22, 25))
#> Decision: Go
#> Go: P(theta > 15 | data) = 0.7403 (threshold 0.6, met)
#> NoGo: P(theta <= 5 | data) = 0.06372 (threshold 0.7, not met)
#> Posterior distributions
#> Treatment: mean ~ t(df = 11, location = 22, scale = 7.217)
#> Control: mean ~ t(df = 11, location = 0, scale = 7.217)Fixed control
With fixed_c, the control mean is a known value
,
for example the mean of the standard of care reported in the literature.
The effect is
,
its probabilities are those of the t distribution of the treatment mean,
and prior_c and method are not used. With the
vague prior and a benchmark of
:
des_fix <- design_continuous(n_t = 12, n_c = 0, prior_t = prior_vague(),
criterion = crit, fixed_c = -10)
dec_fix <- qdm_decide(des_fix, data_t = data_continuous(12, 22, 25))
dec_fix
#> Decision: Go
#> Go: P(theta > 15 | data) = 0.9809 (threshold 0.6, met)
#> NoGo: P(theta <= 5 | data) = 0.00163 (threshold 0.7, not met)
#> Posterior distributions
#> Treatment: mean ~ t(df = 11, location = 22, scale = 7.217)
#> Control: fixed value -10
pt((22 - (-10 + 15)) / (25 / sqrt(12)), df = 11)
#> [1] 0.9809453For the predictive criterion, the mean of the future subjects has the predictive t distribution given above, and the future effect is that mean minus .
Predictive criterion
With 50 subjects per group in a future study and :
des_pred <- design_continuous(
n_t = 12, n_c = 12, prior_t = prior_vague(), prior_c = prior_vague(),
criterion = criterion_predictive(theta_null = 0, m_t = 50,
gamma_go = 0.9, gamma_nogo = 0.7)
)
qdm_decide(des_pred, data_t = data_continuous(12, 22, 25),
data_c = data_continuous(12, 2, 25))
#> Decision: Go
#> Go: P(future theta > 0 | data) = 0.9457 (threshold 0.9, met)
#> NoGo: P(future theta <= 0 | data) = 0.05428 (threshold 0.7, not met)
#> Posterior distributions
#> Treatment: mean ~ t(df = 11, location = 22, scale = 7.217)
#> Control: mean ~ t(df = 11, location = 2, scale = 7.217)Operating characteristics
qdm_oc() simulates nsim studies under each
scenario. Only the sufficient statistics are simulated,
and
with
and
,
and the same random numbers are used for all scenarios. The
moment-matching approximation is much faster than numerical integration
and is convenient for exploring designs:
des_mm <- design_continuous(n_t = 12, n_c = 12, prior_t = prior_vague(),
prior_c = prior_vague(), criterion = crit,
method = "MM")
scen <- data.frame(mu_t = seq(0, 40, by = 5), sd_t = 25, mu_c = 0, sd_c = 25)
oc <- qdm_oc(des_mm, scen, seed = 1)
oc
#> Operating characteristics (simulation of 10000 studies; probabilities by moment-matching approximation)
#> mu_t sd_t mu_c sd_c Go NoGo Gray Miss
#> 0 25 0 25 0.0419 0.4823 0.4758 0
#> 5 25 0 25 0.1087 0.2928 0.5985 0
#> 10 25 0 25 0.2264 0.1533 0.6203 0
#> 15 25 0 25 0.3876 0.0682 0.5442 0
#> 20 25 0 25 0.5825 0.0238 0.3937 0
#> 25 25 0 25 0.7631 0.0069 0.2300 0
#> 30 25 0 25 0.8817 0.0014 0.1169 0
#> 35 25 0 25 0.9508 0.0003 0.0489 0
#> 40 25 0 25 0.9840 0.0001 0.0159 0
plot(oc)
The chosen design can be checked with numerical integration. To keep this vignette quick, only three scenarios and 1000 simulated studies are used here; with the same seed, both methods are applied to the same simulated studies:
scen3 <- scen[c(1, 3, 5), ]
oc_ni <- qdm_oc(des, scen3, nsim = 1000, seed = 1)
oc_mm <- qdm_oc(des_mm, scen3, nsim = 1000, seed = 1)
data.frame(mu_t = scen3$mu_t, Go_NI = oc_ni$Go, Go_MM = oc_mm$Go,
NoGo_NI = oc_ni$NoGo, NoGo_MM = oc_mm$NoGo)
#> mu_t Go_NI Go_MM NoGo_NI NoGo_MM
#> 1 0 0.043 0.043 0.498 0.498
#> 2 10 0.209 0.209 0.180 0.180
#> 3 20 0.575 0.576 0.027 0.027The simulation standard error of the probabilities is at most
,
0.005 for the default nsim = 10000.
Decision boundary
qdm_boundary() shows which observed means lead to each
decision. For each observed standard deviation (or sample size) of the
treatment group, it gives the intervals of the observed treatment mean
that lead to Go, NoGo and Gray decisions, and the corresponding observed
differences in means; the ends of the intervals are located by
bisection. With a concurrent control group, the observed control data
are given by data_c:
b <- qdm_boundary(des_mm, sd_t = seq(10, 40, by = 5),
data_c = data_continuous(12, 2, 25))
b
#> Decision boundary of a design with one continuous endpoint
#> n_t = 12
#> Control data: continuous, n = 12, mean = 2, sd = 25
#>
#> Observed treatment mean
#> sd_t NoGo Gray Go
#> 10 <= 2.747 2.747 to 19.05 >= 19.05
#> 15 <= 2.352 2.352 to 19.24 >= 19.24
#> 20 <= 1.866 1.866 to 19.47 >= 19.47
#> 25 <= 1.321 1.321 to 19.74 >= 19.74
#> 30 <= 0.7346 0.7346 to 20.02 >= 20.02
#> 35 <= 0.1162 0.1162 to 20.31 >= 20.31
#> 40 <= -0.5276 -0.5276 to 20.62 >= 20.62
#>
#> Observed difference in means (control mean 2)
#> sd_t NoGo Gray Go
#> 10 <= 0.7473 0.7473 to 17.05 >= 17.05
#> 15 <= 0.3518 0.3518 to 17.24 >= 17.24
#> 20 <= -0.1338 -0.1338 to 17.47 >= 17.47
#> 25 <= -0.6788 -0.6788 to 17.74 >= 17.74
#> 30 <= -1.265 -1.265 to 18.02 >= 18.02
#> 35 <= -1.884 -1.884 to 18.31 >= 18.31
#> 40 <= -2.528 -2.528 to 18.62 >= 18.62
plot(b)
With an observed standard deviation of 25, a Go decision needs an observed difference in means of at least 17.7, and a larger standard deviation needs a larger observed difference. For the design with a fixed control, the boundary can be shown against the sample size instead:
b_fix <- qdm_boundary(des_fix, n_t = c(6, 12, 20, 30, 40), sd_t = 25)
b_fix
#> Decision boundary of a design with one continuous endpoint
#> sd_t = 25
#>
#> Observed treatment mean
#> n_t NoGo Gray Go
#> 6 <= -10.71 -10.71 to 7.727 >= 7.727
#> 12 <= -8.897 -8.897 to 6.873 >= 6.873
#> 20 <= -7.981 -7.981 to 6.436 >= 6.436
#> 30 <= -7.42 -7.42 to 6.167 >= 6.167
#> 40 <= -7.09 -7.09 to 6.008 >= 6.008
#>
#> Observed difference from the fixed control mean (-10)
#> n_t NoGo Gray Go
#> 6 <= -0.7097 -0.7097 to 17.73 >= 17.73
#> 12 <= 1.103 1.103 to 16.87 >= 16.87
#> 20 <= 2.019 2.019 to 16.44 >= 16.44
#> 30 <= 2.58 2.58 to 16.17 >= 16.17
#> 40 <= 2.91 2.91 to 16.01 >= 16.01
plot(b_fix)
Calibration of the thresholds
The thresholds are calibrated so that the Go criterion is met with probability at most 0.05 when the treatment has no effect, and the NoGo criterion with probability at most 0.2 when the effect is 20:
cal <- qdm_calibrate(
des_mm,
scenario_go = data.frame(mu_t = 0, sd_t = 25, mu_c = 0, sd_c = 25),
scenario_nogo = data.frame(mu_t = 20, sd_t = 25, mu_c = 0, sd_c = 25),
target_go = 0.05, target_nogo = 0.2, seed = 1
)
cal
#> Calibration of the decision thresholds (simulation of 10000 studies; probabilities by moment-matching approximation)
#> gamma_go = 0.57: P(Go criterion met | scenario_go) = 0.0484 (target 0.05)
#> gamma_nogo = 0.28: P(NoGo criterion met | scenario_nogo) = 0.1975 (target 0.2)
#> Decision probabilities with the chosen thresholds
#> scenario mu_t sd_t mu_c sd_c Go NoGo Gray Miss
#> scenario_go 0 25 0 25 0.0484 0.8615 0.0901 0
#> scenario_nogo 20 25 0 25 0.6135 0.1975 0.1890 0
plot(cal)
The chosen thresholds are 0.57 and 0.28.
References
Huang, Y., Yamaguchi, Y., Homma, G., Takeda, K. and Maruo, K. (submitted). Conjugate representation of power priors for efficient Bayesian analysis of normal data.
Kang, R., Yamaguchi, Y. and Han, C. (2026). Bayesian quantitative decision-making framework in cell and gene therapy development for rare diseases. Journal of Biopharmaceutical Statistics. https://doi.org/10.1080/10543406.2026.2655410
Yamaguchi, Y., Homma, G., Takeda, K. and Maruo, K. (submitted). Moment-matching approximation for t-differences in clinical trials with continuous endpoints.
