The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

Multimodel comparison workflows

library(nlmixr2targets)

Why a dedicated multimodel factory?

tar_nlmixr_multimodel() lets you declare several candidate models for the same dataset in one call. Each model gets its own simplify/fit/relabel chain, but the data-simplification step is shared when possible, and within-list piping (models[["A"]] |> ini(...) referenced from another entry) is resolved into a dependency on the prior fit so the data does not have to be re-prepared.

The output is a list of targets you can drop into your _targets.R plan.

Minimal comparison plan

library(targets)
library(tarchetypes)
library(nlmixr2targets)

pheno_base <- function() {
  ini({
    lcl <- log(0.008); label("Typical clearance")
    lvc <- log(0.6); label("Typical volume of distribution")
    etalcl + etalvc ~ c(1, 0.01, 1)
    cpaddSd <- 0.1; label("Additive residual SD")
  })
  model({
    cl <- exp(lcl + etalcl)
    vc <- exp(lvc + etalvc)
    kel <- cl / vc
    d / dt(central) <- -kel * central
    cp <- central / vc
    cp ~ add(cpaddSd)
  })
}

list(
  tar_nlmixr_multimodel(
    name = candidate_fits,
    data = nlmixr2data::pheno_sd,
    est  = "saem",
    "Base"                              = pheno_base,
    "Base + tighter residual prior"     = pheno_base |> ini(cpaddSd = 0.05),
    "Base + alternate residual"         = pheno_base |> model({
      cp ~ prop(cpaddSd)
    }, append = TRUE)
  ),
  tar_target(
    aic_table,
    data.frame(
      model = names(candidate_fits),
      aic   = vapply(candidate_fits, AIC, numeric(1)),
      bic   = vapply(candidate_fits, BIC, numeric(1)),
      ofv   = vapply(candidate_fits, function(f) f$objDf$OBJF[1], numeric(1))
    )
  )
)

After tar_make(), the aic_table target gives you a compact summary of the candidates. Add dAIC or weight columns to taste.

Extracting parameter estimates across models

A common pattern is to pull a particular fixed effect out of every candidate fit to compare:

tar_target(
  clearance_estimates,
  data.frame(
    model = names(candidate_fits),
    lcl   = vapply(
      candidate_fits,
      function(f) f$ui$iniDf$est[f$ui$iniDf$name == "lcl"],
      numeric(1)
    )
  )
)

This works because tar_nlmixr_multimodel() returns a target whose value is a named list of fits.

Within-list piping for nested edits

If the second model is an edit of the first, refer to the first by its key inside the same tar_nlmixr_multimodel() call:

tar_nlmixr_multimodel(
  name = candidate_fits,
  data = nlmixr2data::pheno_sd,
  est  = "saem",
  "Base"            = pheno_base,
  "Tighter residual" =
    candidate_fits[["Base"]] |> ini(cpaddSd = 0.05)
)

Behind the scenes, nlmixr2targets rewrites candidate_fits[["Base"]] to a dependency on the base model’s _fit_simple target. Iteratively resolving these references is what makes within-list piping work without forcing the entire pipeline to re-run when one model changes.

If you write a circular reference (A piping from B and B piping from A) the function errors out at construction time with a clear message.

Tips for large model libraries

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.