nlmixr2
fits are fully supported in the current release,
including many convenience functions to ensure consumed
nlmixr2
results are fully compatible with most all
available features of xpose
and
xpose.xtras
.
Basics
While the xpose.xtras
package already contains a few
nlmixr2
examples, let’s start fresh with a new fit. The
model below is from the
nlmixr2
documentation; to start using the resulting
xpose_data
directly, refer to
?nlmixr2_warfarin
.
pk.turnover.emax3 <- function() {
ini({
tktr <- log(1)
tka <- log(1)
tcl <- log(0.1)
tv <- log(10)
##
eta.ktr ~ 1
eta.ka ~ 1
eta.cl ~ 2
eta.v ~ 1
prop.err <- 0.1
pkadd.err <- 0.1
##
temax <- logit(0.8)
tec50 <- log(0.5)
tkout <- log(0.05)
te0 <- log(100)
##
eta.emax ~ .5
eta.ec50 ~ .5
eta.kout ~ .5
eta.e0 ~ .5
##
pdadd.err <- 10
})
model({
ktr <- exp(tktr + eta.ktr)
ka <- exp(tka + eta.ka)
cl <- exp(tcl + eta.cl)
v <- exp(tv + eta.v)
emax = expit(temax+eta.emax)
ec50 = exp(tec50 + eta.ec50)
kout = exp(tkout + eta.kout)
e0 = exp(te0 + eta.e0)
##
DCP = center/v
PD=1-emax*DCP/(ec50+DCP)
##
effect(0) = e0
kin = e0*kout
##
d/dt(depot) = -ktr * depot
d/dt(gut) = ktr * depot -ka * gut
d/dt(center) = ka * gut - cl / v * center
d/dt(effect) = kin*PD -kout*effect
##
cp = center / v
cp ~ prop(prop.err) + add(pkadd.err)
effect ~ add(pdadd.err) | pca
})
}
fit.TOS <- nlmixr2(pk.turnover.emax3, warfarin, "focei", control=list(print=0),
table=list(cwres=TRUE, npde=TRUE))
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#>
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#>
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> calculating covariance matrix
#> [====|====|====|====|====|====|====|====|====|====] 0:01:12
#> done
Now that we have a fit, we have a few options to consume the results
into xpose
. We could use
xpose.nlmixr2::xpose_data_nlmixr2
and then convert to an
xp_xtras
object from there.
xpose.nlmixr2::xpose_data_nlmixr2(fit.TOS) %>%
as_xp_xtras()
#>
#> ── ~ xp_xtras object
#> Model description: not implemented
#> fit.TOS overview:
#> - Software: nlmixr2 4.1.0
#> - Attached files (memory usage 553.8 Kb):
#> + obs tabs: $prob no.1: nlmixr2
#> + sim tabs: <none>
#> + output files: <none>
#> + special: <none>
#> + fit: <none>
#> - gg_theme: :: xpose theme_readable
#> - xp_theme: xp_xtra_theme new_x$xp_theme
#> - Options: dir = NULL, quiet = TRUE, manual_import = NULL, cvtype = exact
It is helpful though, for traceability and for some convenience
functions for the fit object to be attached to the
xpose_data
object.
xpose.nlmixr2::xpose_data_nlmixr2(fit.TOS) %>%
as_xp_xtras() %>%
attach_nlmixr2(fit.TOS)
#>
#> ── ~ xp_xtras object
#> Model description: not implemented
#> fit.TOS overview:
#> - Software: nlmixr2 4.1.0
#> - Attached files (memory usage 725.7 Kb):
#> + obs tabs: $prob no.1: nlmixr2
#> + sim tabs: <none>
#> + output files: <none>
#> + special: <none>
#> + fit: attached as (this)$fit
#> - gg_theme: :: xpose theme_readable
#> - xp_theme: xp_xtra_theme new_x$xp_theme
#> - Options: dir = NULL, quiet = TRUE, manual_import = NULL, cvtype = exact
One such convenience function is to backfill some of the
"na"
properties pulled from the fit results (at time of
writing, these are condition number and significant digits). It’s
acknowledged that these backfills are opinionated, hence it is
optional.
xpose.nlmixr2::xpose_data_nlmixr2(fit.TOS) %>%
as_xp_xtras() %>%
attach_nlmixr2(fit.TOS) %>%
backfill_nlmixr2_props() %>%
{print(get_prop(., "condn")); .} %>%
get_prop("nsig")
#> [1] "32318.0467755017"
#> [1] "3"
A more useful application of the attached fit result is a method to
make get_prm()
work. Note, xpose::prm_table()
does not work despite this new feature because it uses the original
get_prm()
defined within xpose
namespace.
Since prm_table()
is a quick check convenience function to
print in place, get_prm()
was considered a better function
to get working.
try({
xpose.nlmixr2::xpose_data_nlmixr2(fit.TOS) %>%
as_xp_xtras() %>% xpose::get_prm()
})
#> Error : No `files` slot could be found in this xpdb.
xpose.nlmixr2::xpose_data_nlmixr2(fit.TOS) %>%
as_xp_xtras() %>%
attach_nlmixr2(fit.TOS) %>%
get_prm() %>%
# Remove some columns for readability
dplyr::select(-c(fixed,diagonal,label))
#> # A tibble: 20 × 9
#> type name value se rse m n cv shk
#> <chr> <chr> <num:3> <num:3> <num:3> <int> <int> <num:3> <num:3>
#> 1 the tktr 0.104 2.20 21.1 1 NA NA NA
#> 2 the tka 0.302 2.18 7.23 2 NA NA NA
#> 3 the tcl -2.04 0.109 0.0536 3 NA NA NA
#> 4 the tv 2.06 0.0916 0.0444 4 NA NA NA
#> 5 the prop.err 0.148 NA NA 5 NA NA NA
#> 6 the pkadd.err 0.172 NA NA 6 NA NA NA
#> 7 the temax 4.75 6.20 1.30 7 NA NA NA
#> 8 the tec50 0.157 0.229 1.46 8 NA NA NA
#> 9 the tkout -2.93 0.128 0.0436 9 NA NA NA
#> 10 the te0 4.57 0.0399 0.00874 10 NA NA NA
#> 11 the pdadd.err 3.76 NA NA 11 NA NA NA
#> 12 ome eta.ktr 0.840 NA NA 1 1 101. 62.3
#> 13 ome eta.ka 0.944 NA NA 2 2 120. 60.6
#> 14 ome eta.cl 0.268 NA NA 3 3 27.3 -0.1
#> 15 ome eta.v 0.221 NA NA 4 4 22.4 10.3
#> 16 ome eta.emax 0.590 NA NA 5 5 64.5 95.1
#> 17 ome eta.ec50 0.453 NA NA 6 6 47.7 5.2
#> 18 ome eta.kout 0.153 NA NA 7 7 15.4 32.3
#> 19 ome eta.e0 0.103 NA NA 8 8 10.3 39.6
#> 20 sig sigma(1,1) 1 NA NA 1 1 NA 10.7
To build on this, because nlmixr2
coerces users to use
mu-referencing and captures parameter associations automatically,
another useful backfill includes mapping these parameter associations
with add_prm_association()
, by way of
nlmixr2_prm_associations()
. In this model,
temax
is logit transformed, so to keep assumptions valid in
the CV% calculation it needs to be back-transformed (as indicated in a
cli
message).
xpose.nlmixr2::xpose_data_nlmixr2(fit.TOS) %>%
as_xp_xtras() %>%
attach_nlmixr2(fit.TOS) %>%
nlmixr2_prm_associations() %>%
mutate_prm(temax ~ plogis) %>%
get_prm() %>%
# Remove some columns for readability
dplyr::select(-c(fixed,diagonal,label))
#> # A tibble: 20 × 9
#> type name value se rse m n cv shk
#> <chr> <chr> <num:3> <num:3> <num:3> <int> <int> <num:3> <num:3>
#> 1 the tktr 0.104 2.20 21.1 1 NA NA NA
#> 2 the tka 0.302 2.18 7.23 2 NA NA NA
#> 3 the tcl -2.04 0.109 0.0536 3 NA NA NA
#> 4 the tv 2.06 0.0916 0.0444 4 NA NA NA
#> 5 the prop.err 0.148 NA NA 5 NA NA NA
#> 6 the pkadd.err 0.172 NA NA 6 NA NA NA
#> 7 the temax 0.991 0.362 0.365 7 NA NA NA
#> 8 the tec50 0.157 0.229 1.46 8 NA NA NA
#> 9 the tkout -2.93 0.128 0.0436 9 NA NA NA
#> 10 the te0 4.57 0.0399 0.00874 10 NA NA NA
#> 11 the pdadd.err 3.76 NA NA 11 NA NA NA
#> 12 ome eta.ktr 0.840 NA NA 1 1 101. 62.3
#> 13 ome eta.ka 0.944 NA NA 2 2 120. 60.6
#> 14 ome eta.cl 0.268 NA NA 3 3 27.3 -0.1
#> 15 ome eta.v 0.221 NA NA 4 4 22.4 10.3
#> 16 ome eta.emax 0.590 NA NA 5 5 0.647 95.1
#> 17 ome eta.ec50 0.453 NA NA 6 6 47.7 5.2
#> 18 ome eta.kout 0.153 NA NA 7 7 15.4 32.3
#> 19 ome eta.e0 0.103 NA NA 8 8 10.3 39.6
#> 20 sig sigma(1,1) 1 NA NA 1 1 NA 10.7
#> # Parameter table includes the following associations: tktr~log(eta.ktr),
#> tka~log(eta.ka), tcl~log(eta.cl), tv~log(eta.v), temax~logit(eta.emax),
#> tec50~log(eta.ec50), tkout~log(eta.kout), and te0~log(eta.e0)
That’s a lot of boilerplate to pipe through, so a convenience
function has been developed to cover all of that. Note the parameter
associations are mapped automatically, but we could skip that step if we
weren’t planning to use get_prm()
at all by setting
.skip_assoc=TRUE
.
nlmixr2_warfarin <- nlmixr2_as_xtra(fit.TOS)
General Usage
We covered most of the usage unique to this package in the Basics
section, but this section is to illustrate that common functions will
continue to work. At time of writing, some missing properties are
present and should be added with a PR to
xpose.nlmixr2
(these are not backfill candidates since they
don’t exist in the summary element, violating how
set_prop()
was designed to work).
list_vars(nlmixr2_warfarin)
#> List of available variables for problem no. 1
#> - Subject identifier (id) : ID
#> - Dependent variable (dv) : DV
#> - Independent variable (idv) : TIME
#> - DV identifier (dvid) : DVID [0]
#> - Dose amount (amt) : AMT
#> - Event identifier (evid) : EVID
#> - Model typical predictions (pred) : CPRED
#> - Model individual predictions (ipred) : IPRED
#> - Model parameter (param) : KA, CL, V
#> - Eta (eta) : eta.ktr, eta.ka, eta.cl, eta.v, eta.emax, eta.ec50, eta.kout, eta.e0
#> - Residuals (res) : NPDE, RES, WRES, IRES, IWRES, CRES, CWRES
#> - Categorical covariates (catcov) : SEX [0]
#> - Continuous covariates (contcov) : WT, AGE
#> - Not attributed (na) : NLMIXRLLIKOBS, CMT, EPRED, ERES, NPD, PDE, PD, PRED, ETA.KTR, ETA.KA, ETA.CL, ETA.V, ETA.EMAX, ETA.EC50, ETA.KOUT, ETA.E0, DEPOT, GUT, CENTER, EFFECT, KTR, EMAX, EC50, KOUT, E0, DCP, PD.1, KIN, TAD, DOSENUM
dv_vs_ipred(nlmixr2_warfarin, facet="DVID")
#> Using data from $prob no.1
#> Filtering data by EVID == 0
#> `geom_smooth()` using formula = 'y ~ x'
#> `geom_smooth()` using formula = 'y ~ x'
dv_vs_pred(nlmixr2_warfarin, facet="DVID")
#> Using data from $prob no.1
#> Filtering data by EVID == 0
#> `geom_smooth()` using formula = 'y ~ x'`geom_smooth()` using formula = 'y ~ x'
eta_vs_catcov(nlmixr2_warfarin, etavar = eta.cl)
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> Tidying data by ID, TIME, AMT, DV, DVID ... and 53 more variables
#> Warning: nind is not part of the available keywords. Check ?template_titles for
#> a full list.
eta_vs_contcov(nlmixr2_warfarin, etavar = eta.cl)
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> Tidying data by ID, TIME, AMT, DV, DVID ... and 52 more variables
#> Warning: nind is not part of the available keywords. Check ?template_titles for
#> a full list.
#> `geom_smooth()` using formula = 'y ~ x'
#> `geom_smooth()` using formula = 'y ~ x'
eta_vs_cov_grid(nlmixr2_warfarin, etavar = c(eta.cl,eta.v,eta.ka), quiet=TRUE)
#> Warning: nind is not part of the available keywords. Check ?template_titles for
#> a full list.
eta_vs_cov_grid(nlmixr2_warfarin, etavar = c(eta.kout,eta.e0,eta.emax), quiet=TRUE)
#> Warning: nind is not part of the available keywords. Check ?template_titles for
#> a full list.
Sets
A simple change to the warfarin PK model is to use the same
parameters for ka
and ktr
. In the PD model, we
could also fix emax
to 1
(and drop the
interindividual variability). An analyst would explore these separately
and then maybe combine them, as we have done below.
fit.TOS.kaktr <- fit.TOS %>%
model({
ka <- ktr
}) %>%
nlmixr2(warfarin, "focei",
control = list(print = 0),
table = list(cwres = TRUE, npde = TRUE)
)
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#>
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#>
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> calculating covariance matrix
#> [====|====|====|====|====|====|====|====|====|====] 0:00:43
#> done
fit.TOS.emax1 <- fit.TOS %>%
model({
emax = 1
}) %>%
nlmixr2(warfarin, "focei",
control = list(print = 0),
table = list(cwres = TRUE, npde = TRUE)
)
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#>
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#>
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> calculating covariance matrix
#> [====|====|====|====|====|====|====|====|====|====] 0:00:46
#> done
fit.TOS.simple <- fit.TOS %>%
model({
ka <- ktr
emax = 1
}) %>%
nlmixr2(warfarin, "focei",
control = list(print = 0),
table = list(cwres = TRUE, npde = TRUE)
)
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#>
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#>
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> [====|====|====|====|====|====|====|====|====|====] 0:00:00
#> calculating covariance matrix
#> [====|====|====|====|====|====|====|====|====|====] 0:00:28
#> done
These explorations make up a set which can be examined with an
xpose_set
:
# Since these models were created with piping, need to update their labels
warf_ka <- nlmixr2_as_xtra(fit.TOS.kaktr) %>%
set_prop(run="fit.TOS.kaktr") %>%
# Just to remove github action path
set_option(
dir = paste0("~")
) %>%
set_prop(
dir = paste0("~")
)
warf_emax <- nlmixr2_as_xtra(fit.TOS.emax1) %>%
set_prop(run="fit.TOS.emax1") %>%
set_option(
dir = paste0("~")
) %>%
set_prop(
dir = paste0("~")
)
warf_simple <- nlmixr2_as_xtra(fit.TOS.simple) %>%
set_prop(run="fit.TOS.simple") %>%
set_option(
dir = paste0("~")
) %>%
set_prop(
dir = paste0("~")
)
warfarin_set <- xpose_set(
nlmixr2_warfarin, warf_ka, warf_emax, warf_simple,
.relationships = c(
warf_ka~nlmixr2_warfarin,
warf_emax~nlmixr2_warfarin,
warf_simple ~ warf_ka + warf_emax
)
) %>%
# Add iOFVs
focus_qapply(backfill_iofv)
warfarin_set
#>
#> ── xpose_set object ────────────────────────────────────────────────────────────
#> • Number of models: 4
#> • Model labels: nlmixr2_warfarin, warf_ka, warf_emax, and warf_simple
#> • Number of relationships: 4
#> • Focused xpdb objects: none
#> • Exposed properties: none
#> • Base model: none
warfarin_set$warf_simple
#>
#> ── Part of an xpose_set, with label: warf_simple ───────────────────────────────
#> • Parent(s): warf_ka and warf_emax
#> • In focus?: no
#> • Base model?: no
#>
#> ── xpdb object (accessible with {xpose_set}$warf_simple$xpdb):
#>
#> ── ~ xp_xtras object
#> Model description: not implemented
#> fit.TOS.simple overview:
#> - Software: nlmixr2 4.1.0
#> - Attached files (memory usage 693.4 Kb):
#> + obs tabs: $prob no.1 (modified): na, nlmixr2
#> + sim tabs: <none>
#> + output files: <none>
#> + special: <none>
#> + fit: attached as (this)$fit
#> - gg_theme: :: xpose theme_readable
#> - xp_theme: xp_xtra_theme new_x$xp_theme
#> - Options: dir = ~, quiet = TRUE, manual_import = NULL, cvtype = exact
warfarin_set %>%
expose_property(ofv) %>%
expose_property(condn) %>%
reshape_set() %>%
# Remove some columns for readability
dplyr::select(-c(parent,base,focus))
#> # A tibble: 4 × 4
#> xpdb label ..ofv ..condn
#> <named list> <chr> <dbl> <dbl>
#> 1 <xp_xtras> nlmixr2_warfarin 1400. 3395179.
#> 2 <xp_xtras> warf_ka 1338. 21266.
#> 3 <xp_xtras> warf_emax 1351. 464.
#> 4 <xp_xtras> warf_simple 1338. 269.
warfarin_set %>%
dofv_vs_id(nlmixr2_warfarin, warf_simple, .inorder = TRUE, df=1)
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> Warning: nind is not part of the available keywords. Check ?template_titles for
#> a full list.
warfarin_set %>%
# This comparison should be more interesting
focus_qapply(set_var_types, param=c(KA,EC50), na=c(CL, V)) %>%
prm_waterfall(nlmixr2_warfarin, warf_simple)
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> Tidying data by ID, TIME, AMT, DV, DVID ... and 55 more variables
#> Warning: nind is not part of the available keywords. Check ?template_titles for
#> a full list.
warfarin_set %>%
dv_vs_ipred_modavg(warf_emax, warf_ka)
#> `geom_smooth()` using formula = 'y ~ x'
#> `geom_smooth()` using formula = 'y ~ x'
Derived parameter explorations
The suggestion to have nlmixr2
installed enables
rxode2
utility functions to be leveraged for diagnostics
(and probably many other unrealized benefits, possibly using
nonmem2rx
). One of those features is exploring the derived
parameters for a model.
Now any model (it does not have to be fit with nlmixr2
)
can have derived parameters calculated and checked for signs of
misspecification. The derive_prm()
family of functions can
be used to generate a table of derived parameters or to set derived
parameters as param
type variables.
nlmixr2_m3 %>%
backfill_derived() %>%
list_vars()
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> List of available variables for problem no. 1
#> - Subject identifier (id) : ID
#> - Dependent variable (dv) : DV
#> - Independent variable (idv) : TIME
#> - Dose amount (amt) : AMT
#> - Event identifier (evid) : EVID
#> - Model typical predictions (pred) : CPRED
#> - Model individual predictions (ipred) : IPRED
#> - Model parameter (param) : KA, CL, V, VC, KEL, VSS, T12ALPHA, ALPHA, A, FRACA
#> - Eta (eta) : eta.ka, eta.cl, eta.v
#> - Residuals (res) : RES, WRES, IRES, IWRES, CRES, CWRES
#> - Continuous covariates (contcov) : WT
#> - Not attributed (na) : CMT, CENS, LLOQ, NLMIXRLLIKOBS, PRED, LOWERLIM, UPPERLIM, ETA.KA, ETA.CL, ETA.V, DEPOT, CENT, BLQLIKE, TAD, DOSENUM
derive_prm(nlmixr2_m3) %>%
dplyr::select(ID,KA,CL,VSS:(dplyr::last_col())) %>%
head()
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> ID KA CL VSS T12ALPHA ALPHA A FRACA
#> 1 1 1.7251120 1.729018 28.98376 11.619316 0.05965473 0.03450208 1
#> 2 10 0.7766272 1.877865 26.98758 9.961507 0.06958256 0.03705408 1
#> 3 11 3.1875227 3.793889 35.58941 6.502218 0.10660165 0.02809825 1
#> 4 12 0.9618226 2.418444 26.25119 7.523821 0.09212701 0.03809351 1
#> 5 2 1.8883358 3.263475 31.49839 6.690114 0.10360769 0.03174766 1
#> 6 3 2.2065158 2.938127 32.87793 7.756385 0.08936472 0.03041554 1
# If param has no vars, .prm should be set
pheno_base %>%
backfill_derived(
.prm = c(CL,V)
) %>%
list_vars()
#> Warning: There was 1 warning in `dplyr::mutate()`.
#> ℹ In argument: `type = stringr::str_replace(.$type, "\\d$", "")`.
#> Caused by warning:
#> ! Unknown or uninitialised column: `type`.
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> List of available variables for problem no. 1
#> - Subject identifier (id) : ID
#> - Dependent variable (dv) : DV
#> - Independent variable (idv) : TIME
#> - Dose amount (amt) : AMT
#> - Event identifier (evid) : EVID
#> - Missing dependent variable (mdv) : MDV
#> - Model typical predictions (pred) : PRED
#> - Model individual predictions (ipred) : IPRED
#> - Model parameter (param) : CL, V, VC, KEL, VSS, T12ALPHA, ALPHA, A, FRACA
#> - Eta (eta) : ETA1, ETA2
#> - Residuals (res) : IWRES, CWRES, NPDE, RES, WRES
#> - Categorical covariates (catcov) : APGR ('Apgar score') [10]
#> - Continuous covariates (contcov) : WT ('Weight', kg)
#> - Not attributed (na) : IRES, CRES
These derived parameters can be fed into
diagnose_constants()
to perform some quick checks for
common issues. In this case, we have both VC
(derived) and
V
(fitted) representing the same quantity, so to avoid
catching both in the volume check (which per the documentation should
only be one volume) the vol_pattern
has been updated.
nlmixr2_m3 %>%
backfill_derived() %>%
diagnose_constants(vol_pattern = "^V$")
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> ℹ Checking for absorption flip-flop (first-order absorption slower than derived rate constants)...
#> ✔ No parameter sets are suggestive of flip-flop.
#> ℹ Checking for negative microconstants or volume...
#> ✔ No parameter sets have negative microconstants or volumes.
nlmixr2_m3 %>%
backfill_derived() %>%
diagnose_constants(
vol_pattern = "^V$",
df_units = list(KA = "1/hr", ALPHA = "1/hr"),
checks = list(neg_microvol = FALSE)
)
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> ℹ Checking for absorption flip-flop (first-order absorption slower than derived rate constants)...
#> ✔ No parameter sets are suggestive of flip-flop.
#> ℹ Checking that compared units match...
#> ✔ All relevant units seem to match.
# Using df form
derive_prm(nlmixr2_m3) %>%
diagnose_constants(df = ., vol_pattern = "^V$")
#> Using data from $prob no.1
#> Removing duplicated rows based on: ID
#> ℹ Checking for absorption flip-flop (first-order absorption slower than derived rate constants)...
#> ✔ No parameter sets are suggestive of flip-flop.
#> ℹ Checking for negative microconstants or volume...
#> ✔ No parameter sets have negative microconstants or volumes.
Session info
sessionInfo()
#> R version 4.5.1 (2025-06-13)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.3 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
#> [4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
#> [7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
#> [10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] xpose.xtras_0.1.0 xpose.nlmixr2_0.4.1 xpose_0.4.20
#> [4] ggplot2_3.5.2 rxode2_4.1.0 nlmixr2plot_3.0.3
#> [7] nlmixr2extra_3.0.2 nlmixr2est_4.1.0 nlmixr2data_2.0.9
#> [10] lotri_1.0.2 nlmixr2_4.0.1
#>
#> loaded via a namespace (and not attached):
#> [1] tidyselect_1.2.1 dplyr_1.1.4 farver_2.1.2
#> [4] S7_0.2.0 fastmap_1.2.0 lazyeval_0.2.2
#> [7] GGally_2.4.0 tweenr_2.0.3 rex_1.2.1
#> [10] stringfish_0.17.0 digest_0.6.37 lifecycle_1.0.4
#> [13] magrittr_2.0.3 dparser_1.3.1-13 compiler_4.5.1
#> [16] rlang_1.1.6 sass_0.4.10 tools_4.5.1
#> [19] utf8_1.2.6 yaml_2.3.10 data.table_1.17.8
#> [22] symengine_0.2.10 knitr_1.50 lbfgsb3c_2024-3.5
#> [25] labeling_0.4.3 htmlwidgets_1.6.4 pmxcv_0.0.2
#> [28] RColorBrewer_1.1-3 withr_3.0.2 purrr_1.1.0
#> [31] sys_3.4.3 desc_1.4.3 grid_4.5.1
#> [34] polyclip_1.10-7 scales_1.4.0 MASS_7.3-65
#> [37] cli_3.6.5 rmarkdown_2.29 crayon_1.5.3
#> [40] ragg_1.5.0 generics_0.1.4 RcppParallel_5.1.11-1
#> [43] rstudioapi_0.17.1 tzdb_0.5.0 cachem_1.1.0
#> [46] ggforce_0.5.0 RApiSerialize_0.1.4 stringr_1.5.2
#> [49] splines_4.5.1 vctrs_0.6.5 Matrix_1.7-3
#> [52] jsonlite_2.0.0 PreciseSums_0.7 hms_1.1.3
#> [55] systemfonts_1.2.3 tidyr_1.3.1 jquerylib_0.1.4
#> [58] rxode2ll_2.0.13 glue_1.8.0 pkgdown_2.1.3
#> [61] ggstats_0.10.0 codetools_0.2-20 stringi_1.8.7
#> [64] gtable_0.3.6 tibble_3.3.0 pillar_1.11.0
#> [67] htmltools_0.5.8.1 R6_2.6.1 textshaping_1.0.3
#> [70] conflicted_1.2.0 evaluate_1.0.5 lattice_0.22-7
#> [73] readr_2.1.5 backports_1.5.0 vpc_1.2.2
#> [76] qs_0.27.3 memoise_2.0.1 n1qn1_6.0.1-12
#> [79] bslib_0.9.0 Rcpp_1.1.0 nlme_3.1-168
#> [82] checkmate_2.3.3 mgcv_1.9-3 xfun_0.53
#> [85] fs_1.6.6 forcats_1.0.0 pkgconfig_2.0.3