Skip to contents

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 kk (k=t,ck = t, c), the outcomes follow N(μk,σk2)N(\mu_k, \sigma_k^2), and the data are summarized by the number of subjects nkn_k, the sample mean y‾k\bar y_k and the sample standard deviation sks_k (data_continuous()). The treatment effect is θ=μt−μc\theta = \mu_t - \mu_c.

With the Normal-Inverse-chi-squared prior (prior_nix()), μk∣σk2∼N(μ0,σk2/κ0),σk2∼Inv-χ2(ν0,σ02),\mu_k \mid \sigma_k^2 \sim N(\mu_0, \sigma_k^2 / \kappa_0), \qquad \sigma_k^2 \sim \textrm{Inv-}\chi^2(\nu_0, \sigma_0^2), the posterior distribution has the same form with parameters κn=κ0+n\kappa_n = \kappa_0 + n, μn=(κ0μ0+ny‾)/κn\mu_n = (\kappa_0 \mu_0 + n \bar y) / \kappa_n, νn=ν0+n\nu_n = \nu_0 + n and νnσn2=ν0σ02+(n−1)s2+κ0n(y‾−μ0)2/κn\nu_n \sigma_n^2 = \nu_0 \sigma_0^2 + (n - 1) s^2 + \kappa_0 n (\bar y - \mu_0)^2 / \kappa_n, and the posterior distribution of the mean is the t distribution tνn(μn,σn2/κn)t_{\nu_n}(\mu_n, \sigma_n^2 / \kappa_n). With the vague prior p(μ,σ2)∝σ−2p(\mu, \sigma^2) \propto \sigma^{-2} (prior_vague()), it is tn−1(y‾,s2/n)t_{n - 1}(\bar y, s^2 / n).

For the predictive criterion, the mean of mm future subjects of a group has the posterior predictive distribution tνn(μn,σn2(1κn+1m)).t_{\nu_n}\left(\mu_n, \; \sigma_n^2 \left(\frac{1}{\kappa_n} + \frac{1}{m}\right)\right). Version 0.1.0 of the package used the squared scale σn2(1+1/κn)/m\sigma_n^2 (1 + 1 / \kappa_n) / m, which treats the mm 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 with nMC draws.

Decision for observed data

A study with 12 subjects in each group and vague priors, with θTV=15\theta_{TV} = 15 and θMAV=5\theta_{MAV} = 5:

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 t11(y‾,s2/12)t_{11}(\bar y, s^2 / 12). 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.6791000

Prior 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.214997

External data enter through a power prior with weight a0a_0: data with nen_e subjects, mean y‾e\bar y_e and standard deviation ses_e act as a0nea_0 n_e subjects with the same mean and the sum of squares a0(ne−1)se2a_0 (n_e - 1) s_e^2, which keeps the posterior distribution in closed form (Huang et al., submitted). With the vague prior, the posterior distribution of the mean then has a0ne+n−1a_0 n_e + n - 1 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.7791527

The control mean now has 26 degrees of freedom (0.5×30+12−10.5 \times 30 + 12 - 1), 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 μ0c\mu_{0c} and the squared scale multiplied by rr: μc∼tνnt(μ0c,rσnt2/κnt).\mu_c \sim t_{\nu_{nt}}(\mu_{0c}, \; r \sigma_{nt}^2 / \kappa_{nt}). 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 μc0\mu_{c0}, for example the mean of the standard of care reported in the literature. The effect is θ=μt−μc0\theta = \mu_t - \mu_{c0}, 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 −10-10:

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.9809453

For the predictive criterion, the mean of the mtm_t future subjects has the predictive t distribution given above, and the future effect is that mean minus μc0\mu_{c0}.

Predictive criterion

With 50 subjects per group in a future study and θNULL=0\theta_{NULL} = 0:

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, y‾=μ+σZ/n\bar y = \mu + \sigma Z / \sqrt{n} and s=σX/(n−1)s = \sigma \sqrt{X / (n - 1)} with Z∼N(0,1)Z \sim N(0, 1) and X∼χn−12X \sim \chi^2_{n - 1}, 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.027

The simulation standard error of the probabilities is at most 0.5/nsim0.5 / \sqrt{nsim}, 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 γgo=\gamma_{go} = 0.57 and γnogo=\gamma_{nogo} = 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.