| add_cov_association | R Documentation |
The relationship between a structural parameter and a covariate can be
described, so that the covariate's effect on that parameter – and the
uncertainty of that effect – can later be visualized with
xplot_forest() (via prm_cov()/prm_contcov()/prm_catcov()).
This is deliberately parallel to add_prm_association(): the same
formula-based declaration style, the same two-stage
check-then-process validation, and the same "redeclare to replace"
upsert behavior. It is a separate mechanism (own storage, own getters)
because a covariate association needs more shape than an omega
association – a covariate column, a required reference value, and
(for categorical covariates or custom()) more than one theta – and
it produces a range of effect sizes rather than a single scalar CV.
add_cov_association(xpdb, ..., .problem, .subprob, .method, quiet)
drop_cov_association(xpdb, ..., .problem, .subprob, .method, quiet)
xpdb |
< |
... |
< For |
.problem |
< |
.subprob |
< |
.method |
< |
quiet |
Silence extra output. |
Format for associations is:
LHS ~ fun(COVARIATE, THETA..., ref = ..., ...)
LHS: Selector for a fixed-effect (theta) parameter, exactly as
in add_prm_association() (the{m}, {name} or {label}, unquoted).
Multiple parameters can share one association with + (eg, a
covariate that affects both CL and Q through the same theta).
RHS COVARIATE: The first (positional) argument. The bare,
unquoted name of a contcov/catcov column (see xpose::xp_var()) –
not a fixed-effect or omega selector.
RHS THETA...: One or more further positional arguments,
selecting the fixed-effect parameter(s) that carry the covariate
effect magnitude (same selector rules as LHS – the{m}/{name}/
{label}, unquoted). How many are expected depends on fun; see the
built-in list below.
RHS ref: Required, named, no default, for every
association regardless of fun. This is the covariate value (for
continuous covariates) or raw level (for categorical covariates)
that the effect is normalized against – the point at which the
reported effect ratio is exactly 1. There is no way to safely infer
this from the xpdb alone (NONMEM control streams commonly
normalize a covariate against a hardcoded constant baked into the
code, which is invisible to xpose), so it must always be stated
explicitly, the same way add_prm_association()'s nmboxcox
requires an explicit lambda.
All built-ins express the covariate's effect as a multiplicative
effect_ratio on the parameter's typical value, and are constructed so
that effect_ratio == 1 whenever the covariate equals ref,
regardless of the theta value. Available built-ins:
linear(COV, THETA, ref=): 1 + \theta (COV - ref)
power(COV, THETA, ref=): (COV / ref)^\theta (allometric)
exponential(COV, THETA, ref=): e^{\theta (COV - ref)}
additive(COV, THETA, ref=): (\theta + COV) / (\theta + ref).
An uncommon but simple form where the covariate is added directly (with
an implicit coefficient of 1, unlike linear's explicit slope) to an
intercept-like THETA, eg CL = THETA(n) + WT in the underlying model.
hockey(COV, THETA_LO, THETA_HI, ref=, brk=ref): PsN's
"hockey-stick" two-slope piecewise-linear model –
1 + \theta_{lo} (COV - ref) when COV <= brk,
1 + \theta_{hi} (COV - ref) when COV > brk. brk (the
breakpoint) defaults to ref (PsN's usual default: breakpoint =
normalization reference), but can be given separately, eg for a
covariate normalized to its observed median while the clinically
meaningful cutpoint is a round number (ref = 90, brk = 60 for an
eGFR-like covariate).
catshift(COV, THETA..., ref=): One theta per non-reference
raw level of a categorical covariate, effect_ratio = 1 + THETA_i
for level i (1 at ref). Assumes the typical NONMEM pattern of
one theta per non-reference category (eg
IF (RACE.EQ.2) CLCOV = THETA(9)). Thetas are matched to
non-reference levels in ascending raw-value order – if that order
is ambiguous or wrong for a given model, use custom() instead.
For anything else, custom(COV, THETA..., ref=, fun=) is the escape
hatch: fun is a function of (cov, ref, theta) (theta is always a
numeric vector, even when only one THETA selector is given) returning
the effect ratio. Because custom() can't be verified by
construction the way the built-ins can, add_cov_association()
validates it at declaration time by evaluating fun(ref, ref, theta)
for a few probe values of theta (not the currently-fitted value,
which could coincidentally pass while fun is still wrong for other
theta values) and requires each to equal 1; if it doesn't, the error
states the required invariant and shows what fun actually returned,
rather than failing silently or only much later during plotting.
The computed effect ratio never touches the LHS parameter's own fitted
value – only the covariate-effect theta(s), the covariate value, and
ref – so it does not matter whether the LHS was itself parameterized
on a log, logit, or identity scale in the control stream (get_prm()'s
transform argument only affects diagonal OMEGA/SIGMA reporting
(variance -> SD, covariance -> correlation); THETA values are always
the raw fitted estimate regardless of transform, so there is nothing
to reconcile there either).
What is assumed is that the chosen association – a builtin or
custom() – is an exact match for the functional form actually used
in the model code, including any scale factor baked into that code
(eg a covariate effect entered as THETA(n)*(COV-ref)/100). There is
no way to verify this from the xpdb alone; if a builtin's literal
formula (see above) doesn't match the real model, the result will be
a numerically valid but silently wrong effect ratio, not an error –
the same caveat add_prm_association() already carries for CV%
calculation.
If the covariate-effect theta itself is not already on the scale a
builtin expects (eg it was fitted on a logit or other transformed
scale, or needs some other rescaling to match one of the literal
formulas above), transform it back with mutate_prm() before
declaring the association – the same recommended workflow as
add_prm_association()'s own untransformed-theta requirement.
An updated xp_xtras object
add_prm_association(), prm_cov(), mutate_prm()
# xpdb_x's THETA7 ("CRCL on CL") is a genuine covariate effect already
# in the model, so this is a faithful (if allometric-flavored, for
# illustration) description of it:
xpdb_x %>%
add_cov_association(TVCL ~ power(CLCR, THETA7, ref = 64)) %>%
prm_cov()
# hockey-stick (PsN-style): different slope above/below the reference
xpdb_x %>%
add_cov_association(TVCL ~ hockey(CLCR, THETA7, THETA4, ref = 64)) %>%
prm_cov()
# Categorical: one theta per non-reference level. SEX has 2 levels
# (1, 2), so catshift needs exactly one theta for the non-reference
# level; THETA4 is reused here purely for illustration.
xpdb_x %>%
add_cov_association(TVCL ~ catshift(SEX, THETA4, ref = 1)) %>%
prm_cov()
# custom(): fun(cov, ref, theta) must equal 1 when cov == ref
xpdb_x %>%
add_cov_association(
TVCL ~ custom(CLCR, THETA7, ref = 64,
fun = function(cov, ref, theta) (cov/ref)^theta)
) %>%
prm_cov()
# Dropping an association is easy
bad_assoc <- xpdb_x %>%
add_cov_association(TVCL ~ power(CLCR, THETA7, ref = 64))
bad_assoc %>%
drop_cov_association(TVCL ~ CLCR) %>%
prm_cov()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.