admixr2

R-CMD-check CRAN version CRAN downloads License: GPL v3 Lifecycle: stable DOI Codecov

admixr2 is a meta-analysis framework for population PK/PD. It fits pharmacometric models directly to summary-level data — the mean vector E and covariance matrix V reported per study — instead of individual patient records. The inputs can be digitised aggregate data from published studies, previously published PK/PD models, or a mix of both; the result is a single unified population model with interpretable fixed, random and covariate effects. It integrates with the nlmixr2 / rxode2 ecosystem and provides four estimation backends:

Estimator est = Control
First-Order "adfo" adfoControl()
Monte Carlo "admc" admControl()
Gauss-Hermite "adgh" adghControl()
Iterative Reweighting MC "adirmc" adirmcControl()

Aggregate data modelling

admixr2 implements aggregate data modelling: fitting a nonlinear mixed-effects model to the summary statistics a study reports rather than to individual records. Fitting a single population model jointly across several studies turns them into one meta-analysis — between-study differences are carried by the model itself (inter-individual variability captures subject-level spread within each study; residual error absorbs the rest), while every study shares the same structural and variance parameters and contributes its own dosing regimen, observation times, and sample size.

Two kinds of input feed the analysis:

When to use admixr2

Individual patient data are unavailable — the most common scenario. Published papers report means and standard deviations; regulatory submissions and competitive reasons prevent individual patient data sharing across companies or institutions. admixr2 extracts the maximum information from what is publicly available.

Leveraging the literature for trial design — fit a mechanistic PK/PD model to aggregated results from existing trials, then simulate new dosing regimens or patient populations before committing to a costly study.

Combining evidence across heterogeneous trials — studies differ in dose, formulation, population, or observation schedule. admixr2 handles multi-study fits with per-study dosing events and time grids under a single shared population model.

Reproducing and extending published models — supply a previously published population model directly as input (via datagen()), or digitise its mean concentration–time profiles from figures. No individual patient data required.

Installation

# From CRAN
install.packages("admixr2")

# Development version from GitHub
pak::pak("LeidenPharmacology/admixr2")

Quick start

library(admixr2)
library(rxode2)
library(nlmixr2)

# 1. Compute aggregate statistics from individual data (or digitise from paper)
data("examplomycin")
obs    <- examplomycin[examplomycin$EVID == 0, ]
obs    <- obs[order(obs$ID, obs$TIME), ]
times  <- sort(unique(obs$TIME))
ids    <- unique(obs$ID)
dv_mat <- matrix(NA_real_, nrow = length(ids), ncol = length(times))
for (i in seq_along(ids)) {
  sub         <- obs[obs$ID == ids[i], ]
  dv_mat[i, ] <- sub$DV[order(sub$TIME)]
}
E <- colMeans(dv_mat)
V <- cov.wt(dv_mat, method = "ML")$cov

# 2. Define the model (standard nlmixr2 syntax)
pk_model <- function() {
  ini({
    tcl     <- log(5);  label("Log clearance (L/hr)")
    tv1     <- log(10); label("Log central volume (L)")
    tv2     <- log(30); label("Log peripheral volume (L)")
    tq      <- log(10); label("Log inter-compartmental CL (L/hr)")
    tka     <- log(1);  label("Log absorption rate constant (1/hr)")
    prop.sd <- c(0, 0.2)
    eta.cl ~ 0.09; eta.v1 ~ 0.09; eta.v2 ~ 0.09
    eta.q  ~ 0.09; eta.ka ~ 0.09
  })
  model({
    cl <- exp(tcl + eta.cl); v1 <- exp(tv1 + eta.v1)
    v2 <- exp(tv2 + eta.v2); q  <- exp(tq  + eta.q)
    ka <- exp(tka + eta.ka)
    d/dt(depot)      <- -ka * depot
    d/dt(central)    <- ka * depot - (cl/v1 + q/v1) * central + (q/v2) * peripheral
    d/dt(peripheral) <- (q/v1) * central - (q/v2) * peripheral
    cp <- central / v1
    cp ~ prop(prop.sd)
  })
}

# 3. Fit
fit <- nlmixr2(
  pk_model, admData(), est = "admc",
  control = admControl(
    studies = list(examplomycin = list(
      E = E, V = V, n = length(ids),
      times = times, ev = et(amt = 100)
    )),
    n_sim = 5000L, seed = 1L
  )
)

print(fit)
plot(fit)

Vignettes

Vignette Topic
Getting started Core workflow: data prep, model, fit, diagnostics
From a published figure to E, V and n Error-bar semantics (SD vs SEM vs LS-mean SE), diagonal V, assumed-V sensitivity
Simulating data & using published models datagen() for simulation studies and for supplying published models as input
Multiple studies Joint fitting across studies with different designs
Several outputs (plasma + brain) Multiple observed compartments; joint same-subject V
PD and PK/PD data Effect as a second endpoint, baseline, Emax, predicting an unstudied dose
Estimator comparison adfo, admc, adgh and adirmc: mathematical foundations and when to use each
Choosing a residual error model What cp ~ prop(...) does to E/V, the supported/refused menu, resid_nodes
Advanced usage Gradient modes, parallel restarts, AIC/BIC model comparison
Diagnostic plots All four plot panels explained; IIV heatmap

Citation

If you use admixr2 in your work, please cite the software paper, which introduces the Iterative Reweighting Monte Carlo estimator:

van de Beek H., Välitalo P.A.J., van Hasselt J.G.C., Zwep L.B. (2025). Aggregate data modelling: A fast implementation for fitting pharmacometrics models to summary-level data in R. Journal of Pharmacokinetics and Pharmacodynamics, 53(1), 3. https://doi.org/10.1007/s10928-025-10011-w

The aggregate data modelling methodology is introduced in:

Välitalo P.A.J. (2021). Pharmacometric estimation methods for aggregate data, including data simulated from other pharmacometric models. Journal of Pharmacokinetics and Pharmacodynamics, 48(5), 623–638. https://doi.org/10.1007/s10928-021-09760-1