Overview
Prior elicitation translates an expert’s subjective beliefs about an unknown quantity into a formal probability distribution. bayprior implements the SHELF methodology (O’Hagan et al., 2006) across six distribution families and three elicitation methods.
Distribution Families
Beta
(0, 1)
Response rates, proportions
Normal
(−∞, ∞)
Mean differences, log odds ratios
Gamma
(0, ∞)
Event rates, median survival
Log-Normal
(0, ∞)
Hazard ratios, PK parameters
Exponential
(0, ∞)
Constant hazard rates, Poisson rate priors
Weibull
(0, ∞)
Non-constant hazard survival times (OS, PFS)
Elicitation Methods
Quantile matching — expert specifies probability–value pairs
Moment matching — expert specifies mean and SD
Roulette — expert allocates chips across histogram bins
Beta Prior (Binary Endpoints)
Quantile Matching
prior_q <- elicit_beta (
quantiles = c ("0.05" = 0.10 , "0.50" = 0.30 , "0.95" = 0.60 ),
expert_id = "Expert_1" ,
label = "ORR (treatment arm)"
)
print (prior_q)
-- bayprior: ORR (treatment arm) --
• Distribution : BETA
• Parameters : alpha = 2.6338, beta = 5.589
• Method : quantile elicitation
• Expert : Expert_1
• Mean (SD) : 0.3203 (0.1536)
• 95% CrI : [0.0708, 0.6514]
Moment Matching
prior_m <- elicit_beta (
mean = 0.30 ,
sd = 0.10 ,
method = "moments" ,
expert_id = "Expert_1" ,
label = "ORR (treatment arm)"
)
print (prior_m)
-- bayprior: ORR (treatment arm) --
• Distribution : BETA
• Parameters : alpha = 6, beta = 14
• Method : moments elicitation
• Expert : Expert_1
• Mean (SD) : 0.3 (0.1)
• 95% CrI : [0.1258, 0.512]
Moment matching solves analytically: \[\alpha = \mu \left(\frac{\mu(1-\mu)}{\sigma^2} - 1\right), \quad
\beta = (1-\mu)\left(\frac{\mu(1-\mu)}{\sigma^2} - 1\right)\]
Normal Prior (Continuous Endpoints)
prior_lor <- elicit_normal (
quantiles = c ("0.025" = - 0.50 , "0.50" = 0.20 , "0.975" = 0.90 ),
label = "Log odds ratio"
)
plot (prior_lor)
prior_md <- elicit_normal (
mean = 0.0 , sd = 0.5 , method = "moments" ,
label = "Mean difference (sceptical)"
)
plot (prior_md)
Gamma Prior (Rate and Count Endpoints)
The Gamma distribution is the conjugate prior for Poisson and exponential likelihoods — a natural choice for event rate priors.
prior_os <- elicit_gamma (
mean = 18 , sd = 6 , method = "moments" ,
label = "Median OS (months)"
)
plot (prior_os)
prior_rate <- elicit_gamma (
quantiles = c ("0.10" = 2 , "0.50" = 5 , "0.90" = 10 ),
label = "Event rate (per 100 patient-years)"
)
print (prior_rate)
-- bayprior: Event rate (per 100 patient-years) --
• Distribution : GAMMA
• Parameters : shape = 2.9153, rate = 0.5201
• Method : quantile elicitation
• Expert : Expert_1
• Mean (SD) : 5.6052 (3.2829)
• 95% CrI : [1.1199, 13.6315]
\[\text{mean} = \frac{\text{shape}}{\text{rate}}, \quad
\text{SD} = \frac{\sqrt{\text{shape}}}{\text{rate}}\]
Log-Normal Prior (Hazard Ratios)
prior_hr <- elicit_lognormal (
quantiles = c ("0.05" = 0.40 , "0.50" = 0.70 , "0.95" = 1.20 ),
label = "Hazard ratio (treatment vs control)"
)
plot (prior_hr)
prior_pk <- elicit_lognormal (
mean = 25 , sd = 10 , method = "moments" ,
label = "AUC (ng/mL*h)"
)
print (prior_pk)
-- bayprior: AUC (ng/mL*h) --
• Distribution : LOGNORMAL
• Parameters : meanlog = 3.1447, sdlog = 0.3853
• Method : moments elicitation
• Expert : Expert_1
• Mean (SD) : 25 (10)
• 95% CrI : [10.9089, 49.39]
Exponential Prior (Constant Hazard Rates)
The Exponential distribution models a constant hazard rate \(\lambda > 0\) . The mean is \(1/\lambda\) and the SD equals the mean. It is the conjugate prior likelihood for Gamma priors on Poisson rates, and is appropriate when the hazard rate is assumed constant over time.
Use cases: adverse event rates (events per person-time), constant-hazard survival endpoints, Poisson rate priors for count data.
Method: moments
# Mean hazard rate 0.05 => mean survival 1/0.05 = 20 months
prior_hz <- elicit_exponential (
mean = 0.05 ,
method = "moments" ,
label = "Hazard rate (constant)" ,
expert_id = "Expert_1"
)
print (prior_hz)
-- bayprior: Hazard rate (constant) --
• Distribution : EXPONENTIAL
• Parameters : rate = 20
• Method : moments elicitation
• Expert : Expert_1
• Mean (SD) : 0.05 (0.05)
• 95% CrI : [0.0013, 0.1844]
Method: rate
Direct rate specification (= \(\lambda\) ):
prior_ae <- elicit_exponential (
rate = 0.12 ,
method = "rate" ,
label = "AE rate per person-year"
)
print (prior_ae)
-- bayprior: AE rate per person-year --
• Distribution : EXPONENTIAL
• Parameters : rate = 0.12
• Method : rate elicitation
• Expert : Expert
• Mean (SD) : 8.3333 (8.3333)
• 95% CrI : [0.211, 30.7407]
Method: quantile
Fit the rate from expert-specified quantiles:
prior_hz_q <- elicit_exponential (
quantiles = c ("0.25" = 0.02 , "0.50" = 0.05 , "0.75" = 0.10 ),
method = "quantile" ,
label = "Hazard rate"
)
print (prior_hz_q)
-- bayprior: Hazard rate --
• Distribution : EXPONENTIAL
• Parameters : rate = 14.0345
• Method : quantile elicitation
• Expert : Expert
• Mean (SD) : 0.0713 (0.0713)
• 95% CrI : [0.0018, 0.2628]
Conjugate update
With Poisson/survival data:
\[\text{Prior: Exponential}(\lambda) \approx \text{Gamma}(1, \lambda)\] \[\text{Posterior: Gamma}(1 + x,\; \lambda + n)\]
where \(x\) = observed events, \(n\) = exposure time or follow-up.
Weibull Prior (Non-Constant Hazard Survival Times)
The Weibull distribution is the most widely used model for survival analysis. It is parameterised by shape \(k > 0\) and scale \(\lambda > 0\) :
\[\text{mean} = \lambda\,\Gamma(1 + 1/k), \quad
\text{SD} = \lambda\sqrt{\Gamma(1 + 2/k) - \Gamma(1 + 1/k)^2}\]
Shape parameter interpretation:
\(k < 1\)
Decreasing
Early frailty, selection
\(k = 1\)
Constant
Equivalent to Exponential
\(k > 1\)
Increasing
Ageing, post-surgical deterioration
Method: moments
Specify prior mean and SD — bayprior solves for shape and scale via Nelder-Mead optimisation:
prior_wb <- elicit_weibull (
mean = 20 ,
sd = 10 ,
method = "moments" ,
label = "OS (months)" ,
expert_id = "Expert_1"
)
print (prior_wb)
-- bayprior: OS (months) --
• Distribution : WEIBULL
• Parameters : shape = 2.1014, scale = 22.5813
• Method : moments elicitation
• Expert : Expert_1
• Mean (SD) : 20 (9.9999)
• 95% CrI : [3.9262, 42.0265]
Method: params
Direct shape and scale specification:
# k=2: linearly increasing hazard
prior_wb2 <- elicit_weibull (
shape = 2 ,
scale = 20 ,
method = "params" ,
label = "PFS (months) — increasing hazard"
)
print (prior_wb2)
-- bayprior: PFS (months) — increasing hazard --
• Distribution : WEIBULL
• Parameters : shape = 2, scale = 20
• Method : params elicitation
• Expert : Expert
• Mean (SD) : 17.7245 (9.265)
• 95% CrI : [3.1823, 38.4129]
Method: quantile
prior_wb3 <- elicit_weibull (
quantiles = c ("0.10" = 5 , "0.50" = 18 , "0.90" = 40 ),
method = "quantile" ,
label = "OS (months)"
)
print (prior_wb3)
-- bayprior: OS (months) --
• Distribution : WEIBULL
• Parameters : shape = 1.4822, scale = 22.8859
• Method : quantile elicitation
• Expert : Expert
• Mean (SD) : 20.6908 (14.2043)
• 95% CrI : [1.9159, 55.2137]
Posterior approximation note
The Weibull distribution does not have a closed-form conjugate prior. When used in prior_conflict() or sensitivity_grid(), bayprior applies a Normal approximation to the posterior matched to the Weibull’s fit_summary moments.
Roulette Method
The interactive chip-allocation method for clinical experts unfamiliar with probability distributions. In the Shiny app this is fully interactive; programmatically:
prior_rou <- elicit_roulette (
chips = c (0 L, 1 L, 3 L, 7 L, 9 L, 7 L, 4 L, 2 L, 1 L, 1 L),
breaks = seq (0 , 1 , by = 0.1 ),
family = "beta" ,
label = "Response rate"
)
print (prior_rou)
-- bayprior: Response rate --
• Distribution : BETA
• Parameters : alpha = 3.0457, beta = 3.7685
• Method : quantile elicitation
• Expert : Expert_1
• Mean (SD) : 0.447 (0.1779)
• 95% CrI : [0.1269, 0.7962]
Expert Pooling
Linear Pooling
e1 <- elicit_beta (mean = 0.25 , sd = 0.08 , method = "moments" ,
expert_id = "Oncologist_1" , label = "ORR" )
e2 <- elicit_beta (mean = 0.35 , sd = 0.10 , method = "moments" ,
expert_id = "Oncologist_2" , label = "ORR" )
e3 <- elicit_beta (
quantiles = c ("0.10" = 0.15 , "0.50" = 0.30 , "0.90" = 0.52 ),
expert_id = "Statistician" , label = "ORR"
)
consensus <- aggregate_experts (
priors = list (Oncologist_1 = e1, Oncologist_2 = e2, Statistician = e3),
weights = c (0.40 , 0.35 , 0.25 ),
method = "linear"
)
plot (consensus)
Pooling Compatibility
bayprior validates compatibility before pooling. Priors with incompatible supports (e.g. Beta + Normal) are blocked with an error. Same-support cross-family pooling (e.g. Gamma + Exponential) proceeds with a warning noting that sensitivity analysis will use the dominant component’s parameters.
# Same positive support — allowed (Gamma + Exponential)
g1 <- elicit_gamma (mean = 5 , sd = 2 , method = "moments" ,
expert_id = "E1" , label = "Rate" )
exp1 <- elicit_exponential (mean = 0.2 , method = "moments" ,
expert_id = "E2" , label = "Rate" )
pool_pos <- aggregate_experts (
priors = list (E1 = g1, E2 = exp1),
weights = c (0.5 , 0.5 )
)
print (pool_pos)
-- bayprior: Linear pooled consensus prior --
• Distribution : MIXTURE
• Components : 2
• Weights : 0.5, 0.5
• Mean : 2.6
Prior Object Structure
All elicit_*() functions return a "bayprior" S3 object:
str (prior_q, max.level = 1 )
List of 7
$ dist : chr "beta"
$ params :List of 2
$ method : chr "quantile"
$ expert_id : chr "Expert_1"
$ label : chr "ORR (treatment arm)"
$ input :List of 1
$ fit_summary:List of 5
- attr(*, "class")= chr "bayprior"
$dist
Family: "beta", "normal", "gamma", "lognormal", "exponential", "weibull", "mixture"
$params
Named list of fitted hyperparameters
$fit_summary
mean, sd, q025, q500, q975
$method
Elicitation method
$expert_id
Expert identifier
$label
Quantity label
References
O’Hagan, A. et al. (2006). Uncertain Judgements: Eliciting Experts’ Probabilities . Wiley.
Oakley, J. E. & O’Hagan, A. (2010). SHELF: the Sheffield Elicitation Framework . University of Sheffield.