--- title: "Generalized Linear Mixed-Effects Meta-Analysis" author: "František Bartoš" date: "28th of April 2026" output: rmarkdown::html_vignette: self_contained: yes bibliography: ../inst/REFERENCES.bib csl: ../inst/apa.csl link-citations: true vignette: > %\VignetteIndexEntry{Generalized Linear Mixed-Effects Meta-Analysis} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteEngine{knitr::rmarkdown_notangle} --- ```{r child = "_vignette-nowrap.md", echo = FALSE, eval = TRUE} ``` ```{r setup, include = FALSE} source("vignette-cache.R", local = knitr::knit_global()) cached_fits <- vignette_cache( name = "v13-metafor-parity-glmm", objects = c("fit1_brma"), packages = c("metafor", "metadat") ) knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = vignette_cache_eval(cached_fits), message = FALSE, warning = FALSE, fig.width = 7, fig.height = 3.5, dev = "png", fig.retina = 3 ) if (.Platform$OS.type == "windows") { knitr::opts_chunk$set(dev.args = list(type = "cairo")) } ``` ```{r load-models, include = FALSE} library("metafor") library("RoBMA") data("dat.bcg", package = "metadat") vignette_cache_load(cached_fits) ``` ```{r precompute-models, include = FALSE, eval = FALSE} library("metafor") library("RoBMA") data("dat.bcg", package = "metadat") fit1_brma <- brma.glmm( ai = tpos, bi = tneg, ci = cpos, di = cneg, measure = "OR", data = dat.bcg, seed = 1 ) vignette_cache_save(cached_fits) ``` This vignette illustrates how to use the `RoBMA` R package [@RoBMA] when the outcome is a count rather than an effect-size estimate. We walk through the BCG vaccine dataset from the `metafor` package [@metafor], showing the `brma.glmm()` call alongside its `metafor::rma.glmm()` counterpart for log odds ratios. The interface mirrors `metafor::rma.glmm()`: counts (`ai`, `bi`, `ci`, `di`) are passed in directly, and no `escalc()` step is needed. All `brma.glmm()` calls keep the default prior distributions; see the [*Prior Distributions*](v01-prior-distributions.html) vignette for the prior definitions and customization options. For the non-GLMM workflow showing more features (also applicable to GLMM models) see the [*Bayesian Meta-Analysis*](v02-bayesian-meta-analysis.html) vignette. `brma.glmm()` currently supports binomial outcomes (log odds ratio, `measure = "OR"`) and Poisson outcomes (log incidence rate ratio, `measure = "IRR"`). ## Binomial Random-Effects Model The BCG vaccine dataset from the `metadat` package contains 13 randomized trials on tuberculosis prevention. Treated and control event counts (`tpos`, `tneg`, `cpos`, `cneg`) are passed in directly. ```{r data} data("dat.bcg", package = "metadat") head(dat.bcg) ``` `metafor::rma.glmm()` fits the random-effects logistic model. We use `model = "UM.FS"` to obtain the unconditional model with fixed study-specific intercepts, the formulation that corresponds to the binomial GLMM in `brma.glmm()` (Model 4 in @jackson2018comparison). ```{r fit1-metafor} fit1_metafor <- metafor::rma.glmm( ai = tpos, bi = tneg, ci = cpos, di = cneg, measure = "OR", model = "UM.FS", data = dat.bcg ) fit1_metafor ``` The matching Bayesian fit takes the same count columns and `measure = "OR"`. ```{r fit1-brma, eval = FALSE} fit1_brma <- brma.glmm( ai = tpos, bi = tneg, ci = cpos, di = cneg, measure = "OR", data = dat.bcg, seed = 1 ) ``` `summary()` reports posterior means, credible intervals, and (suppressed here) MCMC convergence diagnostics for the pooled log odds ratio `mu` and the heterogeneity `tau`. ```{r fit1-brma-summary} summary(fit1_brma, include_mcmc_diagnostics = FALSE) ``` The posterior mean for `mu` tracks the maximum-likelihood estimate from the `metafor` package, with comparable heterogeneity `tau`. `pooled_effect()` returns the same summary backtransformed to the odds-ratio scale via `transform = "EXP"`: ```{r fit1-brma-pooled} pooled_effect(fit1_brma, transform = "EXP") ``` ## Default Prior Distributions and the Auxiliary Parameter The default prior distributions on `mu` and `tau` follow the unit-information set-up as elsewhere in the package, scaled by the known unit information standard deviation for the chosen `measure` (`sqrt(4)` for `OR` and `IRR`). Beyond `mu` and `tau`, GLMM models include estimate-specific nuisance parameters for the per-study baseline level. For binomial outcomes (`measure = "OR"`), `logit(pi[i])` is the midpoint of the two arm logits before applying half of the study-specific log odds ratio to each arm. The default `prior_baserate = Beta(1, 1)` is placed independently on each `pi[i]`. For Poisson outcomes (`measure = "IRR"`), `phi[i]` is the midpoint of the two arm log incidence rates before applying half of the study-specific log incidence rate ratio to each arm. Because this midpoint log-rate is unbounded, there is no bounded flat default analogous to `Beta(1, 1)`, so the default `prior_lograte` is a proper data-based unit-information normal used independently for each `phi[i]`. Thus the default nuisance-parameter prior distributions are exchangeable in the iid sense, but they are not hierarchical prior distributions with a learned common baseline-rate distribution. Both defaults can be overridden via the corresponding `prior_*` argument; see the [*Prior Distributions*](v01-prior-distributions.html) vignette. The Poisson model corresponds to @bagos2009mixed and uses event counts and exposure times (`x1i`, `t1i`, `x2i`, `t2i`) in place of the four-way count layout. ## Other Inference Helpers All inference helpers available for any other `brma()` fit work the same way for a `brma.glmm()` fit. Meta-regression via `mods`, multilevel structures via `cluster`, location-scale models via `scale`, posterior summaries, plots, predictions, residuals, influence, and LOO comparisons all carry over. See the [*Bayesian Meta-Analysis*](v02-bayesian-meta-analysis.html) vignette for the full walkthrough and the [*Multilevel Meta-Analysis*](v10-metafor-parity-multilevel.html) vignette for the multilevel extension; the only thing that changes here is the count-based input and the auxiliary baseline-rate prior. ## References