Core 20-S02: Calibrating mixed-model priors with Prior_Setup_GLMM()

library(glmbayesCore)

Core 20-S02: Calibrating mixed-model priors with Prior_Setup_GLMM()

Prior_Setup_GLMM() is the mixed-model counterpart of Prior_Setup() (Core 10). It calls model_setup() (Core 20-S01), uses the classical reference fit, and returns calibrated default priors for both blocks of the hierarchy:

  • Block 2 (population, pop.* fields). For each random coefficient \(k\): a Normal prior on the group-level regression coefficients \(\gamma_k\) (the lme4 fixed effects), a centre for the between-group variance \(\tau^2_k\), and a Gamma prior on the precision \(1/\tau^2_k\) with a truncation window.
  • Block 1 (within group, group.* fields). For Gaussian models, a Gamma prior on the measurement precision. It is either pooled (\(1/\sigma^2\)) or calibrated separately for each group (\(1/\sigma^2_j\)).

As with Prior_Setup(), the defaults are set up so the priors carry a small, explicit fraction of the information in the data.

1. User interface

1.1 Arguments

Passed through to model_setup(). formula, data, family, REML, control, start, verbose, subset, weights, na.action, offset, contrasts, dispformula. These have the meanings described in Core 20-S01. One difference: when control = NULL and the family is Gaussian, Prior_Setup_GLMM() uses lmerControl(optimizer = "bobyqa") with a larger iteration limit.

Block 2: priors on \(\gamma_k\). Supply at most one of pop.pwt, pop.nprior and pop.sd. Each can be a scalar, or a list with one element per random coefficient. Each element can be a scalar or a vector with one value per column of W[[k]].

Argument Default Role
pop.pwt NULL Prior weight \(w \in (0,1)\); prior covariance = reference vcov × \((1-w)/w\)
pop.pwt_default_low, pop.pwt_default_high 0.01, 0.05 Defaults for pop.pwt, chosen per coefficient by \(p_k < 14\) or \(p_k \ge 14\)
pop.nprior NULL Effective prior sample size in group units, \(n = J\,w/(1-w)\)
pop.sd NULL Prior standard deviations on the coefficient scale
pop.intercept_source "null_model" Prior mean of the overall intercept: from a random-intercept-only fit, or from the full model
pop.effects_source "null_effects" Prior means of all other \(\gamma\): zero, or from the full model
pop.mu NULL Explicit prior means; overrides the two *_source arguments for the coefficients supplied

Block 2: priors on \(\tau^2_k\).

Argument Default Role
pop.dispersion.pwt / pop.dispersion.nprior NULL Strength of the Gamma prior on \(1/\tau^2_k\) (at most one); derived from pop.pwt when both are NULL
pop.max_disp_perc 0.99 Tail probability for the \(\tau^2_k\) truncation window (scalar or one per coefficient)

Block 1: priors on \(\sigma^2\) (Gaussian only).

Argument Default Role
group.dispersion.pwt / group.dispersion.nprior NULL (→ 0.01) Strength of the Gamma prior on the measurement precision (at most one); group.dispersion.pwt may be a vector with one value per group
group.max_disp_perc 0.99 Tail probability for the \(\sigma^2\) truncation window(s) (scalar or one per group)
group.alpha_target 0.01 Per-group dispformula only: target rate of out-of-bounds Block 1 draws; searches for each group’s prior weight. NULL disables the search.

1.2 Returned fields

Field(s) Block Content
pop.prior_list 2 Named list, one entry per random coefficient: mu, Sigma, dispersion (\(\hat\tau^2_k\) centre)
pop.pwt, pop.nprior, pop.sd, pop.mu 2 The values actually used, in the same shape the matching argument accepts
pop.dispersion.pwt, pop.dispersion.nprior 2 Strength of the \(\tau^2_k\) prior, one value per coefficient
pop.ing_prior 2 One entry per coefficient: Gamma shape, rate, disp_lower, disp_upper, max_disp_perc
pop.dispersion.ref 2 Classical \(\hat\tau^2_k\) from the reference fit (diagnostic)
group.ing_prior 1 Pooled: one list (shape, rate, disp_lower, disp_upper, …). Per group: a named list with one entry per group
group.dispersion 1 \(\hat\sigma^2\) centre (pooled scalar or per-group vector), with a "source" attribute
group.dispersion.pwt, group.dispersion.nprior, group.max_disp_perc, group.alpha_target, group.pwt_calibration 1 Block 1 prior strength, windows and (per group) the alpha_target search table
group.Sigma, group.tau_sd 1 Diagonal random-effect covariance \(\mathrm{diag}(\hat\tau^2_k)\) and its square roots
group.dispersion.ref, group.dispersion.fit 1 Per-group classical \(\hat\sigma^2_j\) and the glmmTMB fit (per-group dispformula only)
design, mer_fit, fit_ref, calibration_source — The model_setup() object, the lme4 fit, the fit used for calibration and which one it was ("lme4" or "glmmTMB")
block_formula — Within-group formula y ~ 1 + <random slopes> used for Block 1 calibration
formula, family, data, dispformula, pop.intercept_source, pop.effects_source — Inputs

2. Example: Big Word Club

This vignette uses the full-rank Big Word Club data from Core 20-S01.

data(big_word_club, package = "bayesrules")
dat <- big_word_club
dat$school_id <- factor(dat$school_id)
dat <- subset(
  dat,
  !is.na(score_ppvt) &
    !is.na(invalid_ppvt) & invalid_ppvt == 0L &
    complete.cases(dat[, c(
      "score_ppvt", "distracted_a1", "distracted_ppvt",
      "private_school", "title1", "free_reduced_lunch", "school_id"
    )])
)

form_lmer <- score_ppvt ~
  private_school + title1 + free_reduced_lunch +
  distracted_ppvt + distracted_a1 +
  free_reduced_lunch:distracted_a1 +
  (1 + distracted_ppvt + distracted_a1 || school_id)

design0 <- model_setup(form_lmer, data = dat, fit_mer = FALSE)
dat <- subset(dat, school_id %in% names(design0$groupef.rank)[design0$groupef.rank])
dat$school_id <- droplevels(dat$school_id)

2.1 Pooled measurement dispersion (dispformula = ~1)

ps_pooled <- Prior_Setup_GLMM(form_lmer, data = dat, pop.pwt = 0.01)
ps_pooled
#> Call: Prior_Setup_GLMM()
#> 
#> --- Setup ---
#>   Model family, prior-mean sources, and reference fit used for calibration.
#> 
#>   family                : gaussian (identity link)
#>   pop.intercept_source  : null_model
#>   pop.effects_source    : null_effects
#>   dispformula           : ~1
#>   calibration_source    : lme4  (fixef / tau^2_k / sd_tau)
#> 
#> --- Group dispersion (sigma^2) ---
#>   Pooled Gamma prior on sigma^2 is stored in group.ing_prior.
#>   (dGamma_list() requires a per-group dispformula.)
#>   group.dispersion       : 388.8  [pooled S_marg (A12 3.3.4)]
#>   classical lmer sigma^2 : 366.4  (diagnostic)
#> 
#> --- Design check (from model_setup) ---
#>   Identifiability flags copied from the design object (not re-checked here).
#> 
#>   Full-rank groups (algebraic D_j): 34 of 34 school_id
#>   Full-rank & estimable           : 34 of 34 full-rank (34 of 34 total school_id)
#> 
#> --- Group-effect covariance (group.Sigma) ---
#>   Diagonal Psi with entries tau^2_k for each group-effect coefficient.
#> 
#>                 (Intercept) distracted_ppvt distracted_a1
#> (Intercept)        191.7847          0.0000        0.0000
#> distracted_ppvt      0.0000         26.0344        0.0000
#> distracted_a1        0.0000          0.0000       41.0503
#> 
#> --- Population priors (pop.prior_list) ---
#>   One prior list per group-effect coefficient (input to pfamily_list()).
#> 
#>   [(Intercept)]
#>   pop.pwt               : 0.01
#>   pop.dispersion.pwt     : 0.01  [derived from pwt]
#>   pop.dispersion.nprior  : 0.3434  (= J * pwt_disp / (1 - pwt_disp))
#> 
#>   mu:
#>        (Intercept)     private_school             title1 free_reduced_lunch 
#>            88.3756             0.0000             0.0000             0.0000 
#> 
#>   Sigma:
#>                    (Intercept) private_school     title1 free_reduced_lunch
#> (Intercept)          6154.4418     -6078.6768   733.5262           -84.0092
#> private_school      -6078.6768      9380.4431  -738.9706            83.2363
#> title1                733.5262      -738.9706 10055.5989          -117.6066
#> free_reduced_lunch    -84.0092        83.2363  -117.6066             2.4665
#> 
#>   dispersion             : 159.1361  (tau^2_k; A12 3.3.4 marginal)
#>   pop.dispersion.ref     : 191.7847  (classical VarCorr / Psi)
#>   ING tau^2 window       : [91.58, 283.7]  (0.01/0.99 limiting-posterior quantiles; upper/tau2 = 1.78)
#>   ING shape, rate        : 2.672, 266  (Gamma on 1/tau^2_k; for ptypes = "dIndependent_Normal_Gamma")
#> 
#>   [distracted_ppvt]
#>   pop.pwt               : 0.01
#>   pop.dispersion.pwt     : 0.01  [derived from pwt]
#>   pop.dispersion.nprior  : 0.3434  (= J * pwt_disp / (1 - pwt_disp))
#> 
#>   mu:
#> (Intercept) 
#>           0 
#> 
#>   Sigma:
#>             (Intercept)
#> (Intercept)    306.4756
#> 
#>   dispersion             : 6.7375  (tau^2_k; A12 3.3.4 marginal)
#>   pop.dispersion.ref     : 26.0344  (classical VarCorr / Psi)
#>   ING tau^2 window       : [3.877, 12.01]  (0.01/0.99 limiting-posterior quantiles; upper/tau2 = 1.78)
#>   ING shape, rate        : 1.172, 1.157  (Gamma on 1/tau^2_k; for ptypes = "dIndependent_Normal_Gamma")
#> 
#>   [distracted_a1]
#>   pop.pwt               : 0.01
#>   pop.dispersion.pwt     : 0.01  [derived from pwt]
#>   pop.dispersion.nprior  : 0.3434  (= J * pwt_disp / (1 - pwt_disp))
#> 
#>   mu:
#>        (Intercept) free_reduced_lunch 
#>                  0                  0 
#> 
#>   Sigma:
#>                    (Intercept) free_reduced_lunch
#> (Intercept)          1715.5404           -20.7836
#> free_reduced_lunch    -20.7836             0.3412
#> 
#>   dispersion             : 11.4785  (tau^2_k; A12 3.3.4 marginal)
#>   pop.dispersion.ref     : 41.0503  (classical VarCorr / Psi)
#>   ING tau^2 window       : [6.606, 20.47]  (0.01/0.99 limiting-posterior quantiles; upper/tau2 = 1.78)
#>   ING shape, rate        : 1.672, 7.71  (Gamma on 1/tau^2_k; for ptypes = "dIndependent_Normal_Gamma")

2.2 Block 2: Normal priors on \(\gamma_k\)

names(ps_pooled$pop.prior_list)
#> [1] "(Intercept)"     "distracted_ppvt" "distracted_a1"
ps_pooled$pop.prior_list[["(Intercept)"]]$mu
#>        (Intercept)     private_school             title1 free_reduced_lunch 
#>           88.37564            0.00000            0.00000            0.00000
ps_pooled$pop.prior_list[["(Intercept)"]]$Sigma
#>                    (Intercept) private_school     title1 free_reduced_lunch
#> (Intercept)         6154.44179    -6078.67680   733.5262         -84.009160
#> private_school     -6078.67680     9380.44313  -738.9706          83.236339
#> title1               733.52621     -738.97062 10055.5989        -117.606611
#> free_reduced_lunch   -84.00916       83.23634  -117.6066           2.466547

Sigma is the reference fit’s covariance for the fixed effects in W[["(Intercept)"]], scaled by \((1-w)/w\). This is the same convention Prior_Setup() uses for single-level models. The prior mean of the overall intercept comes from a random-intercept-only reference fit, and the other means are zero (the defaults for pop.intercept_source and pop.effects_source).

The three ways of expressing prior strength are always returned with the values actually used. You can inspect them, edit one and pass it back:

ps_pooled$pop.nprior
#> $`(Intercept)`
#>        (Intercept)     private_school             title1 free_reduced_lunch 
#>          0.3434343          0.3434343          0.3434343          0.3434343 
#> 
#> $distracted_ppvt
#> (Intercept) 
#>   0.3434343 
#> 
#> $distracted_a1
#>        (Intercept) free_reduced_lunch 
#>          0.3434343          0.3434343
ps_pooled$pop.sd[["distracted_a1"]]
#>        (Intercept) free_reduced_lunch 
#>         41.4190827          0.5841062
np <- ps_pooled$pop.nprior
np[["(Intercept)"]][] <- 5
ps_np <- Prior_Setup_GLMM(form_lmer, data = dat, pop.nprior = np)
rbind(
  default   = ps_pooled$pop.sd[["(Intercept)"]],
  nprior_5  = ps_np$pop.sd[["(Intercept)"]]
)
#>          (Intercept) private_school    title1 free_reduced_lunch
#> default     78.45025       96.85269 100.27761          1.5705244
#> nprior_5    20.56038       25.38333  26.28094          0.4116058

Raising the effective prior sample size of the intercept regression from about \(0.01 J/0.99\) to 5 schools tightens those prior standard deviations. The other coefficients keep their defaults.

2.3 Block 2: the \(\tau^2_k\) centres and Gamma priors

For Gaussian models, pop.prior_list[[k]]$dispersion is not the classical \(\hat\tau^2_k\). It treats the reference fit’s group coefficients \(\hat b_{\cdot k}\) as data for the regression \(b_{\cdot k} \sim N(W_k\gamma_k, \tau^2_k I_J)\) under the Normal prior above, and takes the marginal variance centre returned by compute_gaussian_prior() (Core 10). The classical value is kept in pop.dispersion.ref:

rbind(
  centre    = sapply(ps_pooled$pop.prior_list, `[[`, "dispersion"),
  classical = ps_pooled$pop.dispersion.ref
)
#>           (Intercept) distracted_ppvt distracted_a1
#> centre       159.1361         6.73747      11.47851
#> classical    191.7847        26.03443      41.05029

pop.ing_prior holds the Gamma prior on \(1/\tau^2_k\) used when pfamily_list() builds independent Normal–Gamma priors (Core 20-S03). With \(n_0\) = pop.dispersion.nprior and \(p_k\) = ncol(W[[k]]):

\[ \text{shape} = \frac{n_0 + 1 + p_k}{2}, \qquad \text{rate} = \hat\tau^2_k \,\frac{n_0 + p_k - 1}{2}, \]

so the implied prior mean of \(\tau^2_k\) equals the centre. The truncation window (disp_lower, disp_upper) comes from quantiles of the limiting posterior \(\Gamma\!\left(\tfrac{J+1}{2}, \hat\tau^2_k\tfrac{J-1}{2}\right)\). This window does not widen as the prior gets weaker. See system.file("ING_TRUNCATION_WINDOW.md", package = "glmbayesCore").

str(ps_pooled$pop.ing_prior[["(Intercept)"]])
#> List of 5
#>  $ shape        : num 2.67
#>  $ rate         : num 266
#>  $ disp_lower   : num 91.6
#>  $ disp_upper   : num 284
#>  $ max_disp_perc: num 0.99

2.4 Block 1: the pooled measurement-precision prior

With dispformula = ~1, group.ing_prior describes a single Gamma prior on \(1/\sigma^2\). Its centre group.dispersion pools within-group marginal residual sums of squares across schools (see Section 3, Stage 10). Its strength is group.dispersion.pwt (default 0.01) relative to the total number of observations.

ps_pooled$group.dispersion
#> [1] 388.8036
#> attr(,"source")
#> [1] "pooled S_marg (A12 3.3.4)"
#> attr(,"classical")
#> [1] 366.4058
str(ps_pooled$group.ing_prior[c("shape", "rate", "disp_lower", "disp_upper")])
#> List of 4
#>  $ shape     : num 4.02
#>  $ rate      : num 1174
#>  $ disp_lower: num 117
#>  $ disp_upper: num 1412

2.5 Per-group measurement dispersion (dispformula = ~ school_id)

With dispformula = ~ school_id (Gaussian only), each school gets its own \(\sigma^2_j\). model_setup() adds a glmmTMB reference fit with a separate dispersion per school. That fit becomes the calibration reference for every calibrated quantity (calibration_source = "glmmTMB"), not just the Block 1 priors.

ps_group <- Prior_Setup_GLMM(
  form_lmer,
  data                 = dat,
  pop.pwt              = 0.01,
  dispformula          = ~school_id,
  group.max_disp_perc  = 0.8,
  group.dispersion.pwt = 0.1,
  group.alpha_target   = NULL
)
ps_group$calibration_source
#> [1] "glmmTMB"

group.ing_prior is now a named list with one entry per school:

gi  <- ps_group$group.ing_prior
fld <- function(nm) vapply(gi, function(e) {
  v <- e[[nm]]
  if (is.null(v)) NA_real_ else as.numeric(v)[1]
}, numeric(1))

head(data.frame(
  n_j        = fld("n_j"),
  sigma2_hat = fld("sigma2_hat"),
  shape_ING  = fld("shape_ING"),
  rate       = fld("rate"),
  disp_lower = fld("disp_lower"),
  disp_upper = fld("disp_upper")
))
#>    n_j sigma2_hat shape_ING      rate disp_lower disp_upper
#> 2   12 1022.27935  2.666667 1703.7989  712.60456  1275.7680
#> 3   13  872.80487  2.722222 1503.1639  616.87100  1084.1978
#> 5   11  447.61608  2.611111  721.1592  307.23020   561.3532
#> 6   11  296.68442  2.611111  477.9916  203.63525   372.0705
#> 9   10   84.45595  2.555556  131.3759   56.96285   106.4661
#> 10  14  311.65922  2.777778  554.0608  223.02386   385.4533

Three settings control these per-group priors:

  • group.dispersion.pwt: each school’s prior weight relative to its own sample size \(n_j\). It may be one value per school.
  • group.max_disp_perc: the tail probability for each school’s window. Narrower windows usually raise the sampler’s acceptance rate.
  • group.alpha_target: when set (default 0.01), searches for each school’s smallest prior weight that keeps the predicted rate of Block 1 draws outside the sampler’s stable region below the target. It only ever strengthens the prior relative to group.dispersion.pwt. It runs a Monte Carlo calculation per school, so it is disabled here to keep the example fast.

2.6 Non-Gaussian families and failed defaults

For binomial(), poisson() and Gamma(), the reference fit is glmer(). There is no Block 1 measurement variance, so group.* dispersion fields are NULL. pop.prior_list[[k]]$dispersion is then the classical \(\hat\tau^2_k\).

Default hyperpriors need a converged reference fit, a fixed main effect for every random slope, and \(\hat\tau^2_k > 0\) for every random coefficient. Otherwise Prior_Setup_GLMM() stops with an error that lists each problem. The usual fix is to add the missing fixed effect or drop a random term whose variance is estimated at zero.

3. Lineage: what runs inside Prior_Setup_GLMM()

3.1 Call tree

The stages run in this order. Helper names are @noRd internals unless marked “exported” or “internal doc”.

Prior_Setup_GLMM(formula, data, ..., pop.*, group.*)
 │
 ├─ STAGE 1  argument checks
 │   └─ check_pwt_scalar() (local), "at most one of" checks, family normalization,
 │      default lmerControl(optimizer = "bobyqa")
 │
 ├─ STAGE 2  design and reference fits
 │   └─ model_setup()                                  exported (S01)
 │
 ├─ STAGE 3  choose the calibration reference
 │   ├─ .lmebayes_dispformula_kind()                    "pooled" / "group"
 │   ├─ .lmebayes_mer_convergence_issues(design$lmer)   must be converged
 │   └─ [dispformula = ~<group>]
 │       ├─ .lmebayes_glmmtmb_convergence_issues(design$glmmTMB_fit)
 │       ├─ extract_glmmtmb_variance_components()       tau^2_k from glmmTMB
 │       └─ .lmebayes_glmmtmb_group_sigma2()            classical sigma^2_j
 │
 ├─ STAGE 4  fixed effects and structural checks
 │   ├─ .lmebayes_reference_fixef(fit_ref)              gamma-hat (lme4 or glmmTMB)
 │   ├─ .lmebayes_reference_vcov(fit_ref)               Var(gamma-hat)
 │   └─ fe_name_for() (local)                           map W[[k]] columns → fixef names;
 │                                                      stop if missing or tau^2_k = 0
 │
 ├─ STAGE 5  resolve prior-strength arguments
 │   ├─ .lmebayes_default_pwt_list()                    pop.pwt = NULL → 0.01 / 0.05 per k
 │   ├─ .lmebayes_resolve_pwt()                         scalar/list → named list per k
 │   ├─ .lmebayes_resolve_mu_override()     ┐
 │   ├─ .lmebayes_resolve_nprior_override() ├─ .lmebayes_resolve_override_list()
 │   ├─ .lmebayes_resolve_sd_override()     ┘
 │   └─ .lmebayes_resolve_disp_prior()                  pop.dispersion.pwt <-> nprior
 │
 ├─ STAGE 6  null intercept fit  [pop.intercept_source = "null_model"]
 │   ├─ lme4::lmer/glmer(y ~ 1 + (1 | g))  or  .lmebayes_fit_glmmtmb_reference()
 │   └─ .lmebayes_mer_convergence_issues() / .lmebayes_glmmtmb_convergence_issues()
 │
 ├─ STAGE 7  Block 2 Normal priors                     → pop.prior_list[[k]]$mu, $Sigma
 │   └─ Sigma_k = vcov[fe_k, fe_k] * outer(s, s),  s = sqrt((1 - w) / w)
 │
 ├─ STAGE 8  Block 2 tau^2_k centres  [gaussian]       → pop.prior_list[[k]]$dispersion
 │   ├─ .lmebayes_block_formula_from_re()               block_formula (used in Stage 10)
 │   └─ for each k:
 │       ├─ .lmebayes_reference_b_component()           b-hat_.k from coef(fit_ref)
 │       │   └─ .lmebayes_reference_coef()
 │       └─ .lmebayes_compute_ing_prior_cal_tau2_hyper()
 │           └─ compute_gaussian_prior()                exported (Core 10)
 │
 ├─ STAGE 9  Block 2 Gamma priors and windows          → pop.ing_prior
 │   ├─ .lmebayes_expand_scalar_or_vector(pop.max_disp_perc)
 │   └─ .lmebayes_ing_limiting_posterior_window()
 │
 ├─ STAGE 10 Block 1 sigma^2 priors  [gaussian]        → group.ing_prior, group.dispersion
 │   ├─ .lmebayes_resolve_measurement_disp_prior()      pooled strength (n-scale)
 │   ├─ [pooled]
 │   │   ├─ .lmebayes_pooled_measurement_smarg_from_groups()
 │   │   │   └─ .lmebayes_measurement_group_smarg_cal()     (each group, see below)
 │   │   └─ .lmebayes_calibrate_ing_prior_measurement()
 │   │       └─ .lmebayes_ing_prior_quantile_window()
 │   └─ [per group]
 │       ├─ .lmebayes_resolve_measurement_disp_prior_group()  per-group strength
 │       ├─ .lmebayes_expand_scalar_or_vector(group.max_disp_perc)
 │       └─ .lmebayes_calibrate_ing_prior_measurement_group()
 │           ├─ .lmebayes_measurement_group_smarg_cal()     (each group)
 │           ├─ .lmebayes_ing_prior_quantile_window()
 │           └─ .lmebayes_ing_prior_list_from_cal()
 │
 │   .lmebayes_measurement_group_smarg_cal()   shared by both branches
 │    ├─ .lmebayes_ing_prior_measurement_group_glm_inputs()  within-group lm, V0, sd
 │    │   └─ .lmebayes_block_formula_prior_mu()               Prior_Setup-style means
 │    ├─ Omega_j[k,k] = W_j[[k]] Sigma_k W_j[[k]]'              gamma uncertainty
 │    └─ .lmebayes_compute_ing_prior_cal_from_sigma()
 │        └─ compute_gaussian_prior()
 │
 ├─ STAGE 11 group.alpha_target search  [gaussian, per group, non-NULL target]
 │   ├─ .lmebayes_calibrate_pwt_measurement_group()
 │   │   ├─ .lmebayes_reference_fixef()
 │   │   ├─ .lmebayes_ing_prior_quantile_window()
 │   │   ├─ .two_block_truncated_omega_moments()
 │   │   └─ stats::uniroot()  per group
 │   ├─ .lmebayes_resolve_measurement_disp_prior_group()   with calibrated weights
 │   └─ .lmebayes_calibrate_ing_prior_measurement_group()  re-run with them
 │
 └─ STAGE 12 assemble the "Prior_Setup_GLMM" object

3.2 Helper reference

Reference-fit accessors (R/glmmtmb_reference_helpers.R). These hide the difference between an lme4 fit and a glmmTMB fit, so Stages 4–11 work unchanged for both.

Helper Role
.lmebayes_dispformula_kind() Validates dispformula; returns "pooled" or "group"
.lmebayes_fit_glmmtmb_reference() Fits glmmTMB() with the given dispformula (also used for the null fit in Stage 6)
.lmebayes_glmmtmb_convergence_issues() Convergence code and Hessian checks for a glmmTMB fit
.lmebayes_reference_fixef(), .lmebayes_reference_vcov(), .lmebayes_reference_coef() Conditional-model fixef(), vcov(), coef() from either fit type
extract_glmmtmb_variance_components() (internal doc) Psi (\(\hat\tau^2_k\)) from a glmmTMB fit, aligned with groupef.names
.lmebayes_glmmtmb_group_sigma2() Per-group classical \(\hat\sigma^2_j\) from the dispersion model

Argument resolvers (R/Prior_Setup_GLMM.R, R/mer_prior_helpers.R)

Helper Role
.lmebayes_default_pwt_list() Default pop.pwt per coefficient: pop.pwt_default_low if \(p_k < 14\), else pop.pwt_default_high
.lmebayes_resolve_pwt() Validates pop.pwt and converts it to a named list of named vectors aligned with W[[k]] columns
.lmebayes_resolve_override_list() Shared resolver for list-shaped overrides (NULL elements keep defaults)
.lmebayes_resolve_mu_override(), .lmebayes_resolve_nprior_override(), .lmebayes_resolve_sd_override() pop.mu, pop.nprior, pop.sd through the shared resolver
.lmebayes_resolve_disp_prior() Converts between pop.dispersion.pwt and pop.dispersion.nprior (\(n_k = J w_k/(1-w_k)\)); default from mean pop.pwt
.lmebayes_expand_scalar_or_vector() “Scalar or one value per unit” expander for *.max_disp_perc (also used by dGamma_list())
.lmebayes_resolve_measurement_disp_prior() Pooled Block 1 strength: \(n_{\mathrm{prior}} = w/(1-w)\,n\)
.lmebayes_resolve_measurement_disp_prior_group() Per-group Block 1 strength: \(n_{\mathrm{prior},j} = w_j/(1-w_j)\,n_j\)
.lmebayes_ing_prior_is_grouped() Tells the pooled and per-group shapes of group.ing_prior apart (used by print and dGamma_list())

Dispersion calibration (R/mer_prior_helpers.R)

Helper Role
.lmebayes_block_formula_from_re() Builds the within-group formula y ~ 1 + <random slopes>
.lmebayes_reference_b_component() Group coefficients \(\hat b_{\cdot k}\) (one per group, in level order) from coef(fit_ref)
.lmebayes_compute_ing_prior_cal_tau2_hyper() Block 2 \(\hat\tau^2_k\) centre: OLS of \(\hat b_{\cdot k}\) on \(W_k\), then compute_gaussian_prior() with the Stage 7 prior
.lmebayes_ing_limiting_posterior_window() \(\tau^2_k\) window from limiting-posterior Gamma quantiles
.lmebayes_ing_prior_measurement_group_glm_inputs() One group’s within-group regression inputs: design, response, OLS covariance \(V_0\), and prior standard deviations from group.tau_sd
.lmebayes_block_formula_prior_mu() Prior_Setup()-style prior means on one group’s data
.lmebayes_measurement_group_smarg_cal() Per-group prior covariance plus \(\Omega_j\) (uncertainty in \(\gamma\) carried through group \(j\)’s row of each \(W_k\)), then compute_gaussian_prior()
.lmebayes_compute_ing_prior_cal_from_sigma() Thin wrapper calling compute_gaussian_prior() with the group inputs
.lmebayes_pooled_measurement_smarg_from_groups() Pooled \(\hat\sigma^2 = \sum_j S_{\mathrm{marg},j} / (n - J p_{\mathrm{re}})\); falls back to intercept-only residuals for a group whose within-group design is singular
.lmebayes_calibrate_ing_prior_measurement() Pooled Block 1 Gamma shape/rate matched to the pooled centre, plus window
.lmebayes_calibrate_ing_prior_measurement_group() Per-group Block 1 calibration: sigma2_hat, shape_ING, rate, n_j, window, max_disp_perc for each group
.lmebayes_ing_prior_list_from_cal() Packs one group’s compute_gaussian_prior() output into its group.ing_prior entry
.lmebayes_ing_prior_quantile_window() disp_lower/disp_upper from Gamma quantiles at a given tail probability
.lmebayes_print_ing_prior_measurement_group_compare() Developer diagnostic; not called by Prior_Setup_GLMM()

group.alpha_target search (R/pwt_measurement_group_calibration.R)

Helper Role
.lmebayes_calibrate_pwt_measurement_group() For each group, simulates the Block 1 draw distribution and uses uniroot() to find the smallest prior weight meeting the target. The result is never below the supplied weight; it also returns the table stored as group.pwt_calibration
.two_block_truncated_omega_moments() Mean and variance of a truncated Gamma precision, used by the search criterion

3.3 How the stages map to returned fields

Returned field Produced in stage
design, mer_fit 2
fit_ref, calibration_source, group.dispersion.ref, group.dispersion.fit 3
pop.pwt, pop.nprior, pop.sd, pop.mu, pop.dispersion.pwt, pop.dispersion.nprior 5, 7
pop.prior_list[[k]]$mu, $Sigma 6, 7
pop.prior_list[[k]]$dispersion, block_formula 8
pop.dispersion.ref, group.Sigma, group.tau_sd 3, 8
pop.ing_prior, pop.max_disp_perc 9
group.ing_prior, group.dispersion, group.dispersion.pwt, group.dispersion.nprior, group.max_disp_perc 10, 11
group.alpha_target, group.pwt_calibration 11