mlumr implements Multilevel Unanchored Meta-Regression (ML-UMR), a population-adjusted indirect treatment comparison method for disconnected evidence networks. ML-UMR extends Multilevel Network Meta-Regression (ML-NMR; Phillippo et al., 2020) to the unanchored setting, where individual patient data (IPD) are available for one treatment and only aggregate data (AgD) are available for the comparator, with no common reference arm (e.g. comparison of single arm studies). In this setting, mlumr estimates treatment effects while adjusting for cross-trial differences in prognostic factors.
In terms of the software, mlumr is an adaptation of the GPL-3
licensed multinma
package, which provides functionality for conducting ML-NMR and
NMAs. mlumr uses similar Sobol quasi-Monte Carlo and Gaussian-copula
integration machinery to marginalize over the comparator-population
covariate distribution, and extends the implementation with Stan
likelihoods for the unanchored two-treatment problem, including SPFA
and relaxed-SPFA models for binomial, normal, and Poisson outcomes.
The package provides three complementary methods within a unified interface:
- ML-UMR (Bayesian): SPFA and Relaxed SPFA models via Stan, with quasi-Monte Carlo integration and Gaussian copula for population adjustment
- STC (Frequentist): Simulated treatment comparison via parametric G-computation with delta-method standard errors
- Naive (Benchmark): Unadjusted comparison of crude outcome summaries
| Family | Outcome type | Link functions |
|---|---|---|
| Binomial | Binary (0/1) | logit (default), probit, cloglog |
| Normal | Continuous | identity (default), log |
| Poisson | Count + exposure | log (default) |
install.packages("mlumr")# install.packages("remotes")
remotes::install_github("choxos/mlumr")mlumr uses Stan for Bayesian model fitting. The default backend is rstan, with Stan model C++ code generated by rstantools and compiled during package installation. A C++ toolchain is required:
- macOS: Install Xcode Command Line Tools (
xcode-select --install) - Windows: Install Rtools
- Linux: Install
g++andmake(usually available by default)
Users who prefer cmdstanr can switch backends after installation:
# Switch to cmdstanr (will offer to install cmdstanr + CmdStan if needed)
mlumr_engine("cmdstanr")
# Switch back to rstan
mlumr_engine("rstan")
# Check current engine
mlumr_engine()The engine preference persists for the current session. To set a permanent
default, add to your .Rprofile:
options(mlumr.stan_engine = "cmdstanr")You can also override the engine for a single model fit:
fit <- mlumr(dat, model = "spfa", engine = "cmdstanr")When the package is attached with library(mlumr), it prints a short
startup message with the installed version and GitHub repository.
A subset of mlumr's exported functions perform similar actions to
their multinma counterparts and intentionally retain the same name
(set_ipd(), set_agd(), add_integration(), unnest_integration(),
distr(), marginal_effects(), qbern()/pbern()/dbern()). mlumr
also exports several functions that are not available in multinma
(mlumr(), naive(), stc(), combine_data(), check_integration(),
conditional_effects(), conditional_predict(), prior_sensitivity(),
calculate_dic()/loo()/waic(), compare_models()).
If both packages are attached in the same R session, R issues masking warnings on the shared names. The cleanest practice is to use only one package per session for any given analysis, matched to the network type (anchored connected → multinma; unanchored disconnected → mlumr). When you do need both attached (e.g. a methods-comparison sensitivity analysis), use the namespace prefix to disambiguate:
library(multinma)
library(mlumr)
# mlumr fits ML-UMR (disconnected, two-trial)
ipd_umr <- mlumr::set_ipd(ipd_df, treatment = "trt", outcome = "outcome",
covariates = c("age_group", "sex"))
fit_umr <- mlumr::mlumr(dat, model = "spfa")
# multinma fits ML-NMR (connected network)
net_nmr <- multinma::set_ipd(pso_ipd, study = studyc, trt = trtc, r = pasi75)
fit_nmr <- multinma::nma(net_nmr, regression = ~ age:.trt)library(mlumr)
set.seed(2026)
# --- Prepare IPD (index treatment) ---
n_A <- 500
ipd_df <- data.frame(
trt = "Drug_A",
outcome = rbinom(n_A, 1, 0.55),
age_group = rbinom(n_A, 1, 0.40),
sex = rbinom(n_A, 1, 0.55)
)
ipd <- set_ipd(ipd_df, treatment = "trt", outcome = "outcome",
covariates = c("age_group", "sex"))
# --- Prepare AgD (comparator) ---
agd_df <- data.frame(
trt = "Drug_B", n_total = 400, n_events = 148,
age_group_mean = 0.35, sex_mean = 0.50
)
agd <- set_agd(agd_df, treatment = "trt",
outcome_n = "n_total", outcome_r = "n_events",
cov_means = c("age_group_mean", "sex_mean"),
cov_types = c("binary", "binary"))
# --- Combine and add integration points ---
dat <- combine_data(ipd, agd)
dat <- add_integration(dat, n_int = 64,
age_group = distr(qbern, prob = age_group_mean),
sex = distr(qbern, prob = sex_mean)
)
# --- Run all three methods ---
# Naive (instant)
naive_result <- naive(dat)
# STC (instant)
stc_result <- stc(dat)
# ML-UMR SPFA (Bayesian, takes a few minutes)
fit <- mlumr(dat, model = "spfa",
prior_intercept = prior_normal(0, 10),
prior_beta = prior_normal(0, 2.5),
chains = 4, iter = 4000, warmup = 2000, seed = 42)
summary(fit)
marginal_effects(fit, effect = "lor")| Feature | ML-UMR SPFA | ML-UMR Relaxed | STC | Naive |
|---|---|---|---|---|
| Covariate adjustment | Joint model | Joint model | Outcome regression | None |
| Effect modification | Assumed absent | Estimated | Not captured | N/A |
| Uncertainty | Posterior | Posterior | Delta method | Delta method |
| Population weighting | QMC integration | QMC integration | G-computation | None |
| Speed | Minutes | Minutes | Sub-second | Sub-second |
| Integration points required | Yes | Yes | Optional | No |
| Function | Purpose |
|---|---|
set_ipd(), set_agd() |
Prepare IPD and AgD with outcome and covariate specification |
combine_data() |
Combine IPD and AgD into a unified dataset |
add_integration() |
Generate QMC integration points with Gaussian copula |
mlumr() |
Fit ML-UMR SPFA or Relaxed model via Stan |
mlumr_engine() |
Get or set the Stan backend (rstan or cmdstanr) |
naive(), stc() |
Frequentist benchmark methods |
predict() |
Population-specific predicted outcomes |
marginal_effects() |
Posterior treatment effect summaries |
conditional_effects() |
Covariate-conditional treatment effects |
conditional_predict() |
Predictions at specific covariate values |
calculate_loo(), calculate_waic(), calculate_dic(), compare_models() |
Bayesian model comparison (LOO-CV, WAIC, DIC) |
| Method | Data required | Type of ITC | Pairwise only | Type of treatment effect | Target population |
|---|---|---|---|---|---|
| MAIC | IPD + AgD | Anchored or unanchored | Yes | Marginal | Comparator |
| STC | IPD + AgD | Anchored or unanchored | Yes | Marginal | Comparator |
| ML-NMR | IPD + AgD | Anchored | No | Marginal or conditional | Any pre-specified target |
| ML-UMR | IPD + AgD | Unanchored | No | Marginal or conditional | Any pre-specified target |
ML-UMR is most appropriate when:
- You have IPD for one treatment and AgD for the comparator
- No common reference arm connects the evidence (unanchored)
- Binary, continuous, or count outcomes are of interest
- Covariate distributions differ between trial populations
Detailed tutorials are available as package vignettes:
vignette("introduction")-- Package overview, installation, and quick startvignette("data-preparation")-- IPD/AgD setup, integration points, and correlation handlingvignette("mlumr-models")-- SPFA vs Relaxed models, priors, diagnostics, and LOO/WAIC/DIC model comparisonvignette("stc-and-naive")-- STC and naive methods with delta-method detailsvignette("model-comparison")-- Side-by-side comparison of all methods with interpretation guidancevignette("worked-example")-- Complete end-to-end analysis from simulated data
The ML-UMR methodology extends the ML-NMR framework:
Phillippo, D. M., Dias, S., Ades, A. E., Belger, M., Brnabic, A., Schacht, A., Saure, D., Kadziola, Z., & Welton, N. J. (2020). "Multilevel Network Meta-Regression for population-adjusted treatment comparisons." Journal of the Royal Statistical Society: Series A, 183(3), 1189--1210. doi:10.1111/rssa.12579
Chandler, C. & Ishak, J. (2025). "Anchors Away: Navigating Unanchored Indirect Comparisons With Multilevel Unanchored Meta-Regression (ML-UMR)." ISPOR Europe 2025, MSR28. Value in Health, 28, S498. https://www.valueinhealthjournal.com/article/S1098-3015(25)05944-3/abstract
Chandler, C. & Ishak, J. (2026). "Surviving Unanchored Indirect Comparisons: An Extension of Multilevel Unanchored Meta-Regression (ML-UMR) for Survival Analyses." ISPOR 2026, MSR131. Value in Health, 29(S6). https://www.ispor.org/heor-resources/presentations-database/presentation-cti/ispor-2026/poster-session-3-3/surviving-unanchored-indirect-comparisons-an-extension-of-multilevel-unanchored-meta-regression-ml-umr-for-survival-analyses
citation("mlumr")- Ahmad Sofi-Mahmudi (author, maintainer)
- Conor Chandler (author)
Portions of the package code, documentation, and Stan models were drafted and audited with the assistance of large language models: Anthropic's Claude Opus 4.6 and 4.7 (via Claude Code) and OpenAI's ChatGPT 5.4 and 5.5 (via Codex). All methodological choices, design decisions, and the final review and validation were performed by the named authors, who take responsibility for the package's contents.
GPL-3. See https://www.gnu.org/licenses/gpl-3.0 for the full license text.