Contents

Overview

The meta-analytic family implements Meta-Analytic Gaussian Network Aggregation (MAGNA): a one-stage random-effects framework for pooling correlation (or covariance) matrices from multiple studies into a single model, while accounting for between-study heterogeneity. The pooled structure can be modeled directly as a correlation matrix (meta_varcov()) or as a Gaussian Graphical Model (meta_ggm()), yielding a meta-analytic partial-correlation network.

Typical use cases include aggregating published correlation matrices of symptom measures into a pooled symptom network, or combining the correlation matrices of several (possibly heterogeneous) samples collected by different labs.

Reference: Epskamp, S., Isvoranu, A. M., & Cheung, M. W.-L. (2022). Meta-analytic Gaussian network aggregation. Psychometrika, 87(1), 12–46. DOI: 10.1007/s11336-021-09764-3

The Random-Effects Model

For each study $s$, the vector of sample correlations $\boldsymbol{r}_s$ is modeled as:

$$\boldsymbol{r}_s = \boldsymbol{\rho} + \boldsymbol{u}_s + \boldsymbol{e}_s$$

Both the pooled structure and the random-effects covariance can be parameterized as cov, chol (default for random effects), prec, ggm, or cor. The square roots of the diagonal of $\boldsymbol{\Sigma}_{\text{RE}}$ are the heterogeneity standard deviations of each correlation, analogous to $\tau$ in univariate meta-analysis.

Data Input

meta_varcov() and meta_ggm() accept three kinds of input:

InputArgumentsNotes
Correlation matrices cors (list) + nobs (vector) The standard MAGNA input. Missing variables in a study may be NA.
Covariance matrices covs (list) + nobs (vector) 0.16 Covariances are now genuinely modeled as covariances (corinput = FALSE); previously they were silently treated as correlations.
Raw data data + studyvar Per-study correlations and sample sizes are computed internally.

Sampling-Variance Methods (Vmethod)

The sampling covariance matrices $\boldsymbol{V}_s$ of the study correlations must be estimated. The Vmethod argument controls how:

VmethodDescription
"individual" (default)Per-study $\boldsymbol{V}_s$ based on each study's own correlations.
"pooled"$\boldsymbol{V}_s$ based on the pooled correlation matrix, scaled by study sample size.
"OS_individual" 0.16Olkin–Siotani (1976) asymptotic covariance of sample correlations, per study.
"OS_pooled" 0.16Olkin–Siotani covariance evaluated at the pooled correlations.
"metaSEM_individual" / "metaSEM_weighted"Compatibility options mirroring the metaSEM package.
Which to choose? The new Olkin–Siotani options (validated against metaSEM::asyCov) are recommended when the heterogeneity (random-effects) variances themselves are of substantive interest. The default is unchanged for backward compatibility with published MAGNA analyses.

The related argument Vestimation ("averaged", the default, or "per_study") controls whether the sampling-error part of the likelihood uses an averaged or per-study weight matrix.

Example: Meta-analytic GGM on Simulated Studies

We simulate 12 studies whose data come from a common chain network ($V_1 - V_2 - V_3 - V_4$, all partial correlations 0.3) with mild between-study heterogeneity, and pool them with meta_ggm(). This example is fully reproducible and runs in seconds:

library("psychonetrics")
library("dplyr")

# --- Simulate per-study correlation matrices ---
set.seed(123)
nStudy <- 12
nv <- 4

# True partial-correlation network (chain): V1 - V2 - V3 - V4
Omega <- matrix(0, nv, nv)
Omega[1, 2] <- Omega[2, 3] <- Omega[3, 4] <- 0.3
Omega <- Omega + t(Omega)

# Implied correlation matrix:
Delta <- diag(1 / sqrt(diag(solve(diag(nv) - Omega))))
trueSigma <- Delta %*% solve(diag(nv) - Omega) %*% Delta

cors <- list(); nobs <- numeric(nStudy)
for (s in seq_len(nStudy)) {
  nobs[s] <- round(runif(1, 200, 600))
  # Study-specific population (between-study heterogeneity):
  P <- cov2cor(trueSigma + crossprod(matrix(rnorm(nv * nv, 0, 0.08), nv, nv)))
  X <- matrix(rnorm(nobs[s] * nv), nobs[s], nv) %*% chol(P)
  cors[[s]] <- cor(X)
  colnames(cors[[s]]) <- rownames(cors[[s]]) <- paste0("V", 1:nv)
}

# --- Fit the meta-analytic GGM ---
mod_meta <- meta_ggm(cors = cors, nobs = nobs,
                     Vmethod = "OS_pooled") %>% runmodel

# Pooled partial-correlation network (recovers the true chain):
round(getmatrix(mod_meta, "omega_y"), 2)

# Heterogeneity SDs per correlation:
round(sqrt(diag(getmatrix(mod_meta, "sigma_randomEffects"))), 3)

# --- Prune to a sparse pooled network ---
mod_meta_pruned <- mod_meta %>% prune(alpha = 0.05, matrices = "omega_y")
compare(saturated = mod_meta, pruned = mod_meta_pruned)
Output (abbreviated)
> round(getmatrix(mod_meta, "omega_y"), 2) [,1] [,2] [,3] [,4] [1,] 0.00 0.30 0.00 0.01 [2,] 0.30 0.00 0.29 0.02 [3,] 0.00 0.29 0.00 0.29 [4,] 0.01 0.02 0.29 0.00 > compare(saturated = mod_meta, pruned = mod_meta_pruned) model DF AIC BIC RMSEA Chisq Chisq_diff DF_diff p_value saturated 0 -175.28 -162.19 pruned 3 -180.21 -168.57 ~ 0 1.08 1.08 3 0.78

The pooled network recovers the true chain structure (edges ≈ 0.30), and pruning correctly removes the three null edges without significant loss of fit (p = 0.78).

Summary

Further Reading