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.

Package {BDIB}


Type: Package
Title: Bayesian Dynamic Information Borrowing for Longitudinal Data with Informative Dropout
Version: 0.1.1
Description: Implements 'BDIB' (Bayesian dynamic information borrowing) for longitudinal outcomes with informative dropout. The package provides the mixture prior for longitudinal data borrowing (MLB) and the self-adapting mixture prior for longitudinal data information borrowing (SLB). Both methods use a shared-parameter model for outcomes and dropout.
License: GPL-3
Encoding: UTF-8
Depends: R (≥ 4.0.0)
Imports: RBesT, jagsUI, stats
Suggests: knitr, rmarkdown, testthat (≥ 3.0.0)
Config/testthat/edition: 3
NeedsCompilation: no
Config/roxygen2/version: 8.0.0
Packaged: 2026-10-08 00:45:36 UTC; saijun
Author: Saijun Zhao [aut, cre]
Maintainer: Saijun Zhao <saijzhao@iu.edu>
Repository: CRAN
Date/Publication: 2026-10-18 15:40:02 UTC

The mixture prior for longitudinal data borrowing (MLB) and self-adapting mixture prior for longitudinal data information borrowing (SLB) Analysis under SPM with MNAR dropout

Description

Arms and notation (H/C/T):

Usage

MLB_SLB_anlaysis(
  historical_df,
  concurrent_df,
  treatment_df,
  family = c("gaussian", "bernoulli"),
  delta,
  n_hist = NULL,
  fixed_weight = 0.5,
  mcmc_settings = list(n.chains = 3, n.iter = 10000, n.burnin = 5000, n.thin = 2,
    parallel = FALSE),
  decision_MLB,
  direction_MLB = c("lower", "higher"),
  decision_SLB,
  direction_SLB = c("lower", "higher")
)

Arguments

historical_df

Long-format data.frame for H with columns id,time,R,Y.

concurrent_df

Long-format data.frame for C with columns id,time,R,Y.

treatment_df

Long-format data.frame for T with columns id,time,R,Y.

family

Character, "gaussian" or "bernoulli" (probit link), passed to SPM.

delta

Clinically significant difference (CSD) used in SLB weight.

n_hist

Positive integer: historical sample size for unit-information prior (continuous only).

fixed_weight

MLB mixing weight \omega (default 0.5).

mcmc_settings

JAGS settings list with fields n.chains,n.iter,n.burnin,n.thin,parallel.

decision_MLB

A REQUIRED decision function for MLB prior with threshold p that takes two numeric vectors of posterior samples (\theta_T,\theta_C) and returns logical/0-1 indicating treatment superiority.

Direction of test (how probabilities are computed/decisions typically defined):

  • Larger-is-better: function(theta_t, theta_c, p=0.95) mean(theta_t > theta_c) > p

  • Smaller-is-better: function(theta_t, theta_c, p=0.95) mean(theta_t < theta_c) > p

direction_MLB

Character scalar specifying the clinical direction of superiority for MLB prior:

  • "lower": smaller is better; report \Pr(\theta_T < \theta_C).

  • "higher": larger is better; report \Pr(\theta_T > \theta_C).

decision_SLB

A REQUIRED decision function for SLB prior with threshold p that takes two numeric vectors of posterior samples (\theta_T,\theta_C) and returns logical/0-1 indicating treatment superiority.

Direction of test (how probabilities are computed/decisions typically defined):

  • Larger-is-better: function(theta_t, theta_c, p=0.95) mean(theta_t > theta_c) > p

  • Smaller-is-better: function(theta_t, theta_c, p=0.95) mean(theta_t < theta_c) > p

direction_SLB

Character scalar specifying the clinical direction of superiority for SLB prior:

  • "lower": smaller is better; report \Pr(\theta_T < \theta_C).

  • "higher": larger is better; report \Pr(\theta_T > \theta_C).

Details

Target parameters \theta_H,\theta_C,\theta_T:

We write \theta_H, \theta_C, \theta_T for the historical, concurrent-control, and treatment arms, respectively.

Workflow (continuous or binary endpoints):

  1. Fit H under SPM with a vague prior on \theta to obtain posterior draws.

  2. Build an informative prior g_0 for \theta_C via RBesT::mixfit on the \theta_H draws.

  3. Build a non-informative prior g_1: Gaussian: unit-information prior from g_0 (inflate SD by \sqrt{n_\mathrm{hist}}); Bernoulli: \mathrm{Beta}(1,1).

  4. Fit C under g_1 to get posterior samples.

  5. Compute SLB weight via posterior-probability-ratio KDE (see SLB_weight).

  6. Construct MLB prior (fixed weight) and SLB prior (data-adaptive weight) via Mixprior.

  7. Fit C under MLB/SLB priors; fit T under g_1.

  8. Posterior comparisons \theta_T vs \theta_C and decisions per direction.

Value

An object of class "mlbslb_result":

Examples

set.seed(1000)
t_vec <- seq(4, 48, 4)
# --- Continuous outcome ---
data_H <- generate_spm(n=60, t_vec, family="gaussian",
                       alpha0=-4, alpha1=0.05, rho=-1, sigma_b=1,
                       theta= -3.2, sigma_e=1)$dat
data_C <- generate_spm(n=30,  t_vec, family="gaussian",
                       alpha0=-4, alpha1=0.05, rho=-1, sigma_b=1,
                       theta= -3.2, sigma_e=1)$dat
data_T <- generate_spm(n=60,  t_vec, family="gaussian",
                       alpha0=-5.3, alpha1=0.05, rho=-1.5, sigma_b=1,
                       theta= -3.7, sigma_e=1)$dat


# Full MCMC fitting takes several minutes.
ans_1 <- MLB_SLB_anlaysis(
  historical_df = data_H, concurrent_df = data_C, treatment_df = data_T,
  family="gaussian", delta=0.5, n_hist=length(unique(data_H$id)), fixed_weight=0.5,
  mcmc_settings = list(n.chains=3, n.iter=10000, n.burnin=5000, n.thin=2, parallel=FALSE),
  decision_MLB = function(theta_t, theta_c, p = 0.95) mean(theta_t < theta_c) > 0.95,
  # Smaller-is-better (treatment < control), p = 0.95
  direction_MLB =  "lower",
  decision_SLB = function(theta_t, theta_c, p = 0.95) mean(theta_t < theta_c) > 0.95,
  # Smaller-is-better (treatment < control), p = 0.95
  direction_SLB =  "lower"
)
ans_1$decisions; ans_1$probabilities


# --- Binary outcome ---
set.seed(1000)
data_H <- generate_spm(n=200, t_vec, family="bernoulli",
                       alpha0=-4, alpha1=0.05, rho=-1, sigma_b=1,
                       theta=0.40, beta0=-2)$dat
data_C <- generate_spm(n=100, t_vec, family="bernoulli",
                       alpha0=-4, alpha1=0.05, rho=-1, sigma_b=1,
                       theta=0.40, beta0=-2)$dat
data_T <- generate_spm(n=200, t_vec, family="bernoulli",
                       alpha0=-5.3, alpha1=0.05, rho=-1.5, sigma_b=1,
                       theta=0.50, beta0=-1.5)$dat


# Full MCMC fitting takes several minutes.
ans_2 <- MLB_SLB_anlaysis(historical_df = data_H, concurrent_df = data_C, treatment_df = data_T,
   family="bernoulli", delta=0.1, n_hist=length(unique(data_H$id)), fixed_weight=0.5,
   mcmc_settings = list(n.chains=3, n.iter=10000, n.burnin=5000, n.thin=2, parallel=FALSE),
   decision_MLB = function(theta_t, theta_c, p = 0.95) mean(theta_t > theta_c) > 0.95,
   # Larger-is-better (treatment > control), p = 0.95
   direction_MLB =  "higher",
   decision_SLB = function(theta_t, theta_c, p = 0.95) mean(theta_t > theta_c) > 0.95,
   # Larger-is-better (treatment > control), p = 0.95
   direction_SLB =  "higher"
)
ans_2$decisions; ans_2$probabilities


Constructing a mixture prior for longitudinal data with informative dropout

Description

The Mixprior function constructs a mixture prior for longitudinal data with informative dropout by mixing an informative prior (built from the historical arm/posterior draws) and a non-informative (e.g., unit-information) prior. It supports both continuous (normMix) and binary (betaMix) outcomes and simply delegates to RBesT::mixcombine.

Usage

Mixprior(informative_prior, noninformative_prior, weight)

Arguments

informative_prior

Informative prior for \theta derived from historical data, represented as RBesT::normMix (continuous) or "betaMix" (binary).

noninformative_prior

Non-informative prior (e.g., unit-information for continuous outcome or Uniform(0,1) for binary outcome) of the same class as informative_prior:

  • Continuous: normMix. See also unit_information_prior().

  • Binary: "betaMix"; commonly RBesT::mixbeta(c(1,1,1)).

weight

Mixture weight assigned to the informative component (0 \leq weight \leq 1); may be a scalar w or a vector c(w, 1-w).

Value

A prior of the same class as informative_prior: normMix for continuous endpoints or "betaMix" for binary endpoints.

Examples

# --- Continuous endpoint (normMix) ---
set.seed(1000)
hist_draws <- rnorm(1000, mean = -3.2, sd = 0.35)
inf_prior_c  <- RBesT::mixfit(hist_draws, type = "norm", Nc = 3)  # informative
nf_prior_c   <- unit_information_prior(inf_prior_c, n_hist = 200) # unit-info
w_c <- 0.6  # (e.g., from SLB_weight)
prior_c <- Mixprior(informative_prior   = inf_prior_c,
                      noninformative_prior = nf_prior_c,
                      weight = w_c)
prior_c

# --- Binary endpoint (betaMix) ---
inf_prior_b <- RBesT::mixbeta(c(1, 20, 30))    # Beta(20,30) as one-component mix
nf_prior_b  <- RBesT::mixbeta(c(1, 1, 1))      # Uniform(0,1)
w_b <- 0.5
prior_b <- Mixprior(informative_prior   = inf_prior_b,
                      noninformative_prior = nf_prior_b,
                      weight = w_b)
prior_b

Self-adapting mixture weight for longitudinal borrowing (SLB)

Description

Given posterior samples of the concurrent control parameter (under a non-informative prior) and a historical point estimate, compute the SLB weight via a kernel-density posterior probability ratio:

R = \frac{\pi(\theta = \theta_h \mid \mathcal{D}_C)} {\max\{ \pi(\theta = \theta_h + \delta \mid \mathcal{D}_C), \pi(\theta = \theta_h - \delta \mid \mathcal{D}_C) \}}, \quad w = \frac{R}{1 + R}.

Usage

SLB_weight(theta_cc_np_samples, theta_h, delta)

Arguments

theta_cc_np_samples

numeric vector. Posterior draws of the concurrent control parameter under a non-informative prior.

theta_h

numeric scalar. Historical estimate.

delta

positive numeric. Clinically significant difference (CSD).

Value

numeric scalar in [0,1].

Examples

set.seed(1000)
# Suppose these are posterior theta samples from concurrent control (NP fit)
theta_cc_np_samples <- rnorm(2000, mean = -3.2, sd = 0.25)

# Historical estimate of theta and clinical delta
theta_h   <- -3.2
delta  <- 0.5

SLB_weight(theta_cc_np_samples, theta_h = theta_h, delta = delta)

Fit SPM with MNAR monotone dropout in JAGS (continuous or binary outcomes)

Description

Unified JAGS interface for the shared-parameter model (SPM) with MNAR dropout:

Usage

fit_spm_jags(
  df,
  family = c("gaussian", "bernoulli"),
  prior_theta = NULL,
  params_to_save = NULL,
  n.chains = 3,
  n.iter = 10000,
  n.burnin = 5000,
  n.thin = 2,
  parallel = FALSE
)

Arguments

df

Long-format data.frame with columns id, time, R, Y. R=1 means observed, R=0 means missing.

family

Either "gaussian" or "bernoulli" (probit).

prior_theta

Optional prior for \theta.

  • family="gaussian": RBesT::normMix object (mixture Normal on \theta).

  • family="bernoulli": a "betaMix" object (mixture Beta on \theta).

If NULL, defaults to a very weak one-component prior.

params_to_save

Character vector of parameter names to monitor. If NULL, sensible defaults are used for each family.

n.chains, n.iter, n.burnin, n.thin

MCMC settings passed to jagsUI::jags.

parallel

Logical; whether to run chains in parallel (via jagsUI).

Value

Numeric vector of posterior draws of \theta.

Examples

# ---- Example 1: Continuous outcome with weak prior ----
set.seed(1000)

# 1) Generate longitudinal data with MNAR monotone dropout
t_vec <- seq(4, 48, 4)
gen <- generate_spm(
  n = 80, t_vec = t_vec, family = "gaussian",
  alpha0 = -4, alpha1 = 0.05, rho = 1, sigma_b = 1,
  theta = -3.2,   # total change at the last visit (= slope * max(t))
  sigma_e = 1
)
df <- gen$dat  # long-format data: id, time, R, Y

# 2) Define a weakly informative prior for theta (one Normal component with large variance)
prior <- RBesT::mixnorm(c(1, 0, 1000))  # weight=1, mean=0, sd=1000

# 3) Fit the SPM (MNAR) and obtain posterior draws of theta

# Full MCMC fitting takes longer than a brief example check.
draws_theta <- fit_spm_jags(
  df = df, family = "gaussian",
  prior_theta = prior,
  params_to_save = c("theta","slope","alpha0","alpha1","rho","sigma_e","sigma_b"),
  n.chains = 3, n.iter = 10000, n.burnin = 5000, n.thin = 2, parallel = FALSE
)

# Summarize posterior results
summary(draws_theta)    # posterior mean, median, quantiles
mean(draws_theta)       # posterior mean of theta


# ---- Example 2: Binary outcome (probit link) with weak prior ----
set.seed(1000)
# 1) Generate longitudinal binary data with MNAR monotone dropout
t_vec <- seq(4, 48, 4)
gen <- generate_spm(
  n       = 200,
  t_vec   = t_vec,
  family  = "bernoulli",
  alpha0  = -4,       # dropout logit-intercept
  alpha1  =  0.05,    # dropout logit-slope in time
  rho     = -1,       # association between random effect and dropout
  sigma_b =  1,       # SD of random intercept b_i
  theta   =  0.4,    # target marginal Pr(Y=1) at final visit
  beta0   = -2        # outcome probit-intercept
)
df <- gen$dat  # long-format data: id, time, R, Y

# 2) Define a weakly informative prior for theta:
#    Beta(1,1) (Uniform on (0,1)) as a one-component mixture
prior <- RBesT::mixbeta(c(1, 1, 1))  # weight=1, a=1, b=1

# 3) Fit the SPM (MNAR) with probit link for the binary outcome
#    and obtain posterior draws of theta (final-visit response rate)

# Full MCMC fitting takes longer than a brief example check.
draws_theta <- fit_spm_jags(
  df             = df,
  family         = "bernoulli",
  prior_theta    = prior,
  params_to_save = c("theta","slope","beta0","alpha0","alpha1","rho","sigma_b"),
  n.chains       = 3,
  n.iter         = 5000,
  n.burnin       = 3000,
  n.thin         = 2,
  parallel       = FALSE
)

# 4) Summarize posterior results
summary(draws_theta)   # posterior mean, median, quantiles of theta
mean(draws_theta)      # posterior mean of theta


Gaussian Kernel Density Estimation

Description

Gaussian Kernel Density Estimation

Usage

gaussian_kde(samples, eval_points, bandwidth = NULL)

Arguments

samples

Numeric vector of samples.

eval_points

Numeric vector of locations to evaluate.

bandwidth

Optional bandwidth; Silverman's rule if NULL.

Value

Numeric vector of density estimates.

Examples

set.seed(1000)
xs <- rnorm(1000, mean = -3, sd = 0.5)
pts <- seq(-4.5, -1.5, length.out = 5)
dens <- gaussian_kde(xs, pts)      # KDE values at 'pts'
cbind(pts, round(dens, 4))

Generate longitudinal data from a shared-parameter model (SPM) with MNAR monotone dropout (continuous or binary outcomes)

Description

Generate longitudinal data from a shared-parameter model (SPM) with MNAR monotone dropout (continuous or binary outcomes)

Usage

generate_spm(
  n,
  t_vec,
  family = c("gaussian", "bernoulli"),
  alpha0,
  alpha1,
  rho,
  sigma_b,
  theta,
  beta0 = NA_real_,
  sigma_e = NA_real_
)

Arguments

n

Integer. Sample size (number of subjects).

t_vec

Numeric vector of visit times.

family

Character. Either "gaussian" for a continuous outcome or "bernoulli" for a binary outcome.

alpha0, alpha1

Numerics. Intercept and time slope in the dropout model (logit link).

rho

Numeric. Coupling between the shared random effect b_i and the dropout model; \rho \neq 0 induces MNAR.

sigma_b

Numeric (>0). Standard deviation of the subject-specific random intercept b_i \sim \mathcal{N}(0, \sigma_b^2).

theta

Numeric. Target effect:

  • family="gaussian": change at final visit _K: \theta = \beta_1 t_K (so the slope is \beta_1=\theta/t_K).

  • family="bernoulli": marginal response probability at the final visit in (0,1) (probit link).

beta0

Numeric. For family="bernoulli" only: probit intercept in \Phi(\beta_0 + \beta_1 t_k + b_i). Ignored for "gaussian".

sigma_e

Numeric (>0). For family="gaussian" only: residual SD.

Details

Outcome model (shared-parameter).

Dropout model (MNAR, monotone).

\mathrm{logit}\,\Pr(R_{ik}=0 \mid R_{i,k-1}=1, b_i) = \alpha_0 + \alpha_1 t_k + \rho b_i,

and once dropout occurs (R_{ik}=0), all subsequent R_{i,k'}=0 for k'>k.

Value

A list with:

Ymat

n \times K matrix of outcomes (NA for missing).

Rmat

n \times K matrix of response indicators (1=observed, 0=missing).

dat

Long-format data.frame with columns id, time, R, Y.

Examples

set.seed(1000)
t_vec <- seq(4, 48, 4)
# Continuous outcome
out_c <- generate_spm(
  n = 50, t_vec = t_vec, family = "gaussian",
  alpha0 = -4, alpha1 = 0.05, rho = -1, sigma_b = 1,
  theta = -3.2, sigma_e = 1
)
# Binary outcome
out_b <- generate_spm(
  n = 200, t_vec = t_vec, family = "bernoulli",
  alpha0 = -4, alpha1 = 0.05, rho = -1, sigma_b = 1,
  theta = 0.4, beta0 = -2
)

Unit-Information Prior for continuous outcomes

Description

Constructs a unit-information (weak) prior from an informative normMix by inflating each component's standard deviation by \sqrt{n_h}.

Usage

unit_information_prior(informative_prior, n_hist)

Arguments

informative_prior

A normMix (from RBesT) built from historical data.

n_hist

Positive integer: historical sample size n_h.

Value

A normMix with inflated standard deviations.

Examples

# Start with an informative prior from historical samples via RBesT::mixfit
set.seed(1000)
fake_hist_draws <- rnorm(300, mean = -3.2, sd = 0.4)
inf_prior <- RBesT::mixfit(fake_hist_draws, type = "norm", Nc = 3)

nf_prior <- unit_information_prior(inf_prior, n_hist = 300)
# Compare SDs before/after
rbind(
  informative_sd  = as.numeric(inf_prior[3, ]),
  unit_info_sd    = as.numeric(nf_prior[3, ])
)

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.