--- title: "Introduction to mlumr" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction to mlumr} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE, purl = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE, message = FALSE, warning = FALSE ) ``` ## Overview **mlumr** implements multilevel unanchored meta-regression (ML-UMR) for indirect treatment comparisons using individual patient data (IPD) and aggregate data (AgD). It supports binary, continuous (normal), and count (Poisson) outcomes. It provides: - **ML-UMR** (Bayesian): SPFA and Relaxed SPFA models via Stan (`rstan` by default, with optional `cmdstanr`) - **STC**: Simulated treatment comparison via parametric G-computation - **Naive**: Unadjusted comparison as a benchmark Version 0.1.0 is a two-treatment package: one treatment is represented by IPD (the index treatment) and one by AgD (the comparator treatment). Multi-treatment unanchored networks are outside the current package scope. ## When to use mlumr Use mlumr when you need to compare two treatments that have never been directly compared in the same trial (disconnected network), and you have: - **IPD** from one trial (index treatment) - **AgD** from another trial (comparator treatment) - Shared covariates between populations - Binary, continuous, or count outcomes ## Installation ```{r, eval = FALSE, purl = FALSE} # From GitHub (development version) # install.packages("remotes") remotes::install_github("choxos/mlumr") ``` ## Quick start The pipeline below runs on toy data so every chunk is self-contained. For a more detailed worked analysis, see `vignette("worked-example")`. ```{r, eval = TRUE} library(mlumr) set.seed(2026) # Toy IPD: trial A (index treatment, binary outcome) n_a <- 300 trial_a_data <- data.frame( trt = "Drug_A", response = rbinom(n_a, 1, 0.55), age_cat = rbinom(n_a, 1, 0.40), sex = rbinom(n_a, 1, 0.55) ) # Toy AgD: trial B (comparator treatment) trial_b_data <- data.frame( trt = "Drug_B", n_total = 400, n_events = 160, age_cat_mean = 0.35, sex_mean = 0.50 ) ``` ```{r, eval = TRUE} # 1. Prepare IPD ipd <- set_ipd( data = trial_a_data, treatment = "trt", outcome = "response", covariates = c("age_cat", "sex") ) # 2. Prepare AgD agd <- set_agd( data = trial_b_data, treatment = "trt", outcome_n = "n_total", outcome_r = "n_events", cov_means = c("age_cat_mean", "sex_mean"), cov_types = c("binary", "binary") ) # 3. Combine dat <- combine_data(ipd, agd) # 4. Add integration points (needed for ML-UMR) dat <- add_integration( dat, n_int = 64, age_cat = distr(qbern, prob = age_cat_mean), sex = distr(qbern, prob = sex_mean) ) ``` ```{r, eval = TRUE, purl = FALSE} # 5. Fit ML-UMR fit_spfa <- mlumr( dat, model = "spfa", chains = 2, iter = 500, warmup = 250, seed = 42, refresh = 0, verbose = FALSE ) fit_relaxed <- mlumr( dat, model = "relaxed", chains = 2, iter = 500, warmup = 250, seed = 43, refresh = 0, verbose = FALSE ) # 6. Compare summary(fit_spfa) compare_models(fit_spfa, fit_relaxed) # 7. Frequentist benchmarks naive_result <- naive(dat) stc_result <- stc(dat) print(naive_result) print(stc_result) ``` Before using results in a real analysis, inspect integration quality and posterior diagnostics: ```{r, eval = TRUE, purl = FALSE} check_integration( dat, age_cat = distr(qbern, prob = age_cat_mean), sex = distr(qbern, prob = sex_mean) ) prior_summary(fit_spfa) fit_spfa$diagnostics max(fit_spfa$summary$Rhat, na.rm = TRUE) min(fit_spfa$summary$n_eff, na.rm = TRUE) ``` ## Choosing a method | Method | Adjusts for covariates? | Effect modification? | Inference | |--------|------------------------|---------------------|-----------| | ML-UMR SPFA | Yes | No (shared betas) | Bayesian | | ML-UMR Relaxed | Yes | Yes (treatment-specific betas) | Bayesian | | STC | Yes (outcome model only) | No | Frequentist | | Naive | No | N/A | Frequentist | - **ML-UMR SPFA** is appropriate when prognostic factors affect both treatments equally. - **ML-UMR Relaxed** is appropriate when you suspect treatment-by-covariate interactions (effect modification). - **STC** adjusts for imbalances through an outcome model and uses integration points when available; best when treatment effects do not vary with covariates. - **Naive** serves as a benchmark only; do not use for inference in the presence of cross-trial differences.