---
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
