The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

bayprior bayprior logo

CRAN status R CMD check codecov Live App

Structured Bayesian prior elicitation, conflict diagnostics, and regulatory reporting.


Overview

bayprior is an advanced interactive R package and Shiny application designed for biostatisticians and clinical researchers to implement Bayesian Prior Elicitation, Conflict Diagnostics, and Sensitivity Analysis for clinical trials.

bayprior focuses on a specific stage of the Bayesian trial workflow: how do you construct, validate, and justify your prior to a regulator? It brings structured elicitation, prior-data conflict diagnostics, and regulatory report generation together in one integrated workflow. The FDA’s 2026 draft guidance on Bayesian methods makes this a growing area of focus.

bayprior enables users to:


Features and Modules

Module Detail Primary Output Goal
Prior Elicitation Quantile matching, moment matching, SHELF roulette for Beta / Normal / Gamma / Log-Normal / Exponential / Weibull Fitted density plot + parameter table Structured expert prior elicitation
Expert Pooling Linear and logarithmic opinion pooling with support compatibility validation Consensus density overlay + Bhattacharyya matrix Aggregate multi-expert beliefs
MAP Prior (Historical) Meta-analytic-predictive prior via random-effects meta-analysis, with an explicit prior on between-trial heterogeneity (tau) Fitted prior + tau posterior plot Derive an informative prior from historical trials
Conflict Diagnostics Box p-value (Normal approximation or exact prior predictive), S-value (surprisal), surprise index, KL divergence, Bhattacharyya overlap; binary, continuous, Poisson, and survival data Prior-Likelihood-Posterior overlay Detect prior misspecification
Mahalanobis Check Two-endpoint multivariate conflict test Chi-sq p-value + per-parameter z-scores Co-primary endpoint trials
Sensitivity Analysis Hyperparameter grid over posterior mean, SD, CrI width, Pr(efficacy); independent data entry Tornado plot + influence heatmap Demonstrate robustness to regulators
Sceptical Prior Spiegelhalter-Freedman centred-at-null prior Prior density + summary statistics Conservative regulatory sensitivity
Robust Mixture Schmidli et al. MAP robust mixture prior Robust vs informative density overlay Protection against misspecification
Power Prior Ibrahim-Chen calibrated borrowing weight via Bayes Factor Calibration curves + optimal delta Principled historical data borrowing
Export Report HTML / PDF / Word (.docx) prior justification document via Quarto Regulatory-ready self-contained report Submission documentation

Core Methodology

Prior Elicitation

Three structured elicitation approaches are implemented. Quantile matching fits a parametric distribution to expert-specified probability-value pairs via numerical optimisation. Moment matching derives hyperparameters analytically from an expert-supplied mean and SD. The SHELF roulette method (Oakley & O’Hagan, 2010) lets the expert allocate chips across histogram bins, fitting a parametric family to the chip allocation in real time.

All three methods support six distribution families:

Family Support Typical use
Beta (0, 1) Response rates, proportions
Normal (-Inf, Inf) Mean differences, log odds ratios
Gamma (0, Inf) Event rates, variances, survival times
Log-Normal (0, Inf) Hazard ratios, PK parameters
Exponential (0, Inf) Constant hazard rates, Poisson rate priors
Weibull (0, Inf) Non-constant hazard survival times (OS, PFS)

MAP Prior (Historical Data)

The meta-analytic-predictive (MAP) approach (Schmidli et al., 2014) derives an informative prior directly from multiple historical trials via a random-effects meta-analysis, with an explicit prior on the between-trial heterogeneity parameter tau – how much heterogeneity is assumed among historical trials directly affects how much borrowing is justified, so map_prior() requires this to be stated rather than left as an unstated default (see ?resolve_tau_prior for outcome-specific defaults). It returns an ordinary prior object that can be used directly, or passed into robust_prior() for an additional vague-mixture component.

y/se per historical trial can be supplied directly, or derived from raw trial-level summary statistics via the optional convenience function historical_effect_sizes(), a thin wrapper around metafor::escalc() (metafor is Suggests-only and not required to use map_prior() itself).

Prior-Data Conflict Diagnostics

Conflict detection follows Box (1980). Complementary metrics are computed:

By default the Box p-value uses a Normal approximation to the prior and the likelihood. prior_conflict(..., exact = TRUE) instead uses the exact prior predictive distribution where one has a closed form: Beta-Binomial (Beta prior, binary data) and Gamma-Poisson / Negative Binomial (Gamma prior, Poisson or survival data). Other combinations fall back to the Normal approximation with a message, and $box_pvalue_method reports which was used.

Four data types are supported:

Data type Conjugate update Typical endpoint
Binary (x events / n) Beta-Binomial Response rate, ORR
Continuous (mean, SD, n) Normal-Normal Mean difference
Poisson / count (events / exposure) Gamma-Poisson Adverse event rate
Survival (events / follow-up time) Gamma-Exponential Hazard rate, OS, PFS

Sensitivity Analysis

The sensitivity module is fully independent of conflict diagnostics — users can enter observed data directly without running conflict diagnostics first. Results are visualised as tornado plots and influence heatmaps. A dedicated sensitivity_cri() function tracks credible interval width specifically — a key regulatory quantity.

Robust and Power Priors

The robust mixture prior (Schmidli et al., 2014) mixes the informative prior with a vague Normal component. The sceptical prior (Spiegelhalter & Freedman, 1994) is centred at the null treatment effect. The power prior (Ibrahim & Chen, 2000) down-weights historical data by delta in (0, 1], calibrated to achieve a target Bayes Factor.


Shiny application

run_app() launches the full workflow as an interactive app (also available as a live demo). The Welcome page shows the analytical workflow, tracks which steps you have completed, and can load a synthetic Phase II example (TRIAL-001) so you can try the conflict check straight away.


Installation

Type Source Command
Release CRAN install.packages("bayprior")
Development GitHub pak::pak("ndohpenngit/bayprior")

PDF reports require Quarto CLI and a LaTeX installation:

install.packages("tinytex")
tinytex::install_tinytex()

Quick Start

library(bayprior)

# Elicit a Beta prior
prior <- elicit_beta(mean = 0.35, sd = 0.10, method = "moments",
                     label = "Response rate", expert_id = "Expert_1")
plot(prior)

# Pool two experts
e1  <- elicit_beta(mean = 0.30, sd = 0.10, method = "moments", expert_id = "E1")
e2  <- elicit_beta(mean = 0.42, sd = 0.12, method = "moments", expert_id = "E2")
agg <- aggregate_experts(list(E1 = e1, E2 = e2), weights = c(0.6, 0.4))

# Conflict diagnostics (add exact = TRUE for the exact prior predictive p-value)
cd <- prior_conflict(prior, list(type = "binary", x = 18, n = 40))
print(cd)

# Derive a MAP prior from historical trials (log-odds scale)
hist_prior <- map_prior(
  y  = qlogis(c(0.28, 0.35, 0.31)),   # historical response rates, as log-odds
  se = c(0.30, 0.26, 0.34),           # their standard errors
  outcome_type = "single_arm_log_odds"
)
plot(hist_prior)

# Sensitivity analysis
sa <- sensitivity_grid(
  prior,
  data_summary = list(type = "binary", x = 18, n = 40),
  param_grid   = list(alpha = seq(1, 8, 0.5), beta = seq(2, 20, 1)),
  target       = c("posterior_mean", "prob_efficacy"),
  threshold    = 0.30
)
plot_tornado(sa)

# Robust and sceptical priors
rob  <- robust_prior(prior, vague_weight = 0.20)
scep <- sceptical_prior(null_value = 0.20, family = "beta",
                        strength = "moderate")

# Generate regulatory report
prior_report(
  prior           = prior,
  conflict        = cd,
  sensitivity     = sa,
  robust_prior    = rob,
  sceptical_prior = scep,
  output_format   = "html",
  trial_name      = "TRIAL-001",
  sponsor         = "Example Pharma Ltd",
  author          = "N.P., Biostatistician"
)

# Launch the Shiny app
run_app()

Vignettes

Vignette Covers
bayprior-introduction Full end-to-end workflow overview
prior-elicitation All six families and three elicitation methods
conflict-diagnostics All four data types; univariate and multivariate
sensitivity-analysis Grid sensitivity, tornado plots, CrI tracking
robust-priors MAP priors from historical trials, robust mixture, sceptical, and power priors
regulatory-reporting Report generation and compliance checklist
using-with-rstanarm-brms Passing bayprior priors to rstanarm and brms models
browseVignettes("bayprior")

Documentation

Documentation

Full documentation — vignettes, changelog, and cheat sheet. Function help is available in R via help(package = "bayprior") or ?bayprior.


Code of Conduct

Please note that the bayprior project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.


References

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.