For each requested effect, predicts over a grid of that predictor
with every other predictor held at a reference value (numeric: mean;
factor: first level; matrix covariate: column means) and random
effects excluded (re_formula = NA). Confidence bands are Wald
intervals computed on the link scale and back-transformed. Smooth
terms are part of the predicted curve; conditional_smooths() draws
each smooth term on its own, as brms's function of that name does.
Usage
conditional_effects(x, ...)
# S3 method for class 'frmtmb_fit'
conditional_effects(
x,
effects = NULL,
resp = NULL,
dpar = NULL,
resolution = 100,
prob = 0.95,
method = c("epred", "predict"),
band = c("wald", "profile", "boot"),
re_formula = NA,
ndraws = 400,
boot = NULL,
profile_points = 25,
seed = NULL,
conditions = list(),
surface = FALSE,
spaghetti = FALSE,
select_points = 0,
too_far = 0,
data = NULL,
int_conditions = list(),
categorical = NULL,
...
)Arguments
- x
A
frmtmb_fit.- ...
allow_new_levels, passed topredict.frmtmb_fit(). Anything else is reported as unknown, by name, againstconditional_effects().- effects
Character vector of variable names, or
"x:z"pairs; for a pair, the first variable is varied over its range while the second is held at its levels (factors) or at mean and mean plus or minus one SD (numeric). Default: every fixed-effect and smooth variable of the selected linear predictor, plus one"a:b"pair per fitted interaction (brms's default); a term of order three or more contributes its leading pair. A named effect is valid when each of its variables is one the model reads (a predictor of any parameter, or a grouping variable), as in brms. An invalid effect among valid ones is dropped with brms's warning "Some specified effects are invalid for this model", and when none is valid the call stops with brms's "All specified effects are invalid for this model". A variable that is in the data but not in the model is invalid.- resp, dpar
Response and distributional parameter, as in
predict.frmtmb_fit().- resolution
Number of grid points for a varied numeric predictor.
- prob
Coverage of the confidence bands (brms spelling).
- method
"epred"(default): Wald bands for the expected response, which for a family whose mean is not the inverse link of itsmupredictor (zero-inflated, hurdle,trials(), truncated) is the MEAN and not that predictor. brms's own spellings"posterior_epred"and"posterior_predict"are accepted as aliases."predict": prediction intervals - quantile bands fromndrawsresponses simulated from the family at each grid point (observation noise; random effects stay excluded, as in brms withre_formula = NA), withestimate__the MEDIAN of the same draws, as brms reports the median of its predictive draws: on the scale of the draws (a count undertrials(), inside the bounds undertrunc()), and a whole count for a discrete family whenndrawsis odd. It is not the expected response, whichmethod = "epred"shows. The draws respect the response's addition terms. As in brms, atrials()variable thatconditionsdoes not set is held at 1, and the variable of anse()term or atrunc()bound at its mean, like every other variable. An expression bound is evaluated on the grid, where the response is at its mean too, sotrunc(lb = min(y) - 1)ismean(y) - 1. Set the variable inconditionsfor a bound of your choice. On the draws offrmtmb.sample::frm_sample(),"predict"draws one response per grid row and posterior draw, at the parameters of that draw, so the band is the posterior predictive band that brms draws: under the draws method's defaultrobust = TRUE,estimate__is its median andse__its MAD. There, as in brms,transformapplies to the predicted draws before they are summarized, with brms's warning that the argument is deprecated, andseedfixes the simulation.- band
How the confidence band is built:
"wald"(default, the delta method on the scale the band is symmetric on),"profile"(likelihood-root inversion per grid point) or"boot"(parametric-bootstrap percentiles). See the band section. Only formethod = "epred".- re_formula
The population switch, in brms's spelling:
NA(the default) draws the population-level curve,NULLconditions on a NEW, unobserved group, and a one-sided formula keeps the named terms for one.NAremoves the(x | g)group-level terms and keeps every SMOOTH, as brms does, so on a model withs(x, g, bs = "fs")the drawn curve is the grouping factor's reference level's, that being where the display holds a predictor it is not varying. A new group's conditional modes are zero, so its curve IS the population curve and what the group costs is spread: the band carries the random-effect variance on top of the coefficient uncertainty, and the grouping column of the returned frame isNAto say which group it is.band = "boot"carries it too, by drawing that group's effects once per bootstrap replicate rather than by adding a variance. To condition on an OBSERVED group, name it inconditions(conditions = list(g = "3")) or vary it as an effect (effects = "x:g"). The rule is brms's, whose display predicts withallow_new_levels = TRUE: per grid row and per group-level term, the term reads its fitted effects where every one of its grouping variables is set to a level the fit saw, and a NEW level everywhere else, which covers a variable left unset orNA, a level the fit never saw ("99", which the frame keeps), and a nested(1 | g / h)withgset andhunset, whereg's effect is read and a newg:hlevel is drawn within it. Each distinct new level is drawn once per replicate (per posterior draw on draws) and shared by the rows and panels that name it. brms draws a new group's random effects afresh from the fitted covariance in every posterior draw, so its curve is stochastic around this one; a maximum-likelihood fit has the mode and the variance instead of draws.predict.frmtmb_fit()spells the same setting the same way; lme4'sre.formis refused and says so.band = "profile"exists only for the population-level curve.- ndraws
Simulated responses per grid point for
method = "predict". For the draws method: how many evenly spaced posterior draws the curves are computed over (default all).- boot
For
band = "boot":NULL(default) runs onefrm_bootstrap()of 200 refits and says so, a number runs that many, and afrmtmb_bootobject from an earlier identical call (attr(ce, "boot")) is reused without refitting anything.- profile_points
For
band = "profile": how many points of a numeric grid are profiled, the band being interpolated between them on the link scale.- seed
Seed for
band = "boot", passed tofrm_bootstrap().- conditions
Named list overriding reference values, e.g.
list(x2 = 1, g = "b"); or a data frame whose rows define multiple condition sets (brms style), labeled by acond__column from its row names.- surface
TRUEdraws a two-variable effect"x1:x2"of two numeric predictors as a surface: both vary over their range atresolutionvalues each,effect2__stays numeric, andplot()draws an image with contours. brms's argument, with brms's meaning.FALSE(the default) varies the first predictor at three values of the second.- spaghetti
TRUEadds one curve per draw as the attribute"spaghetti"of an effect whose first predictor is numeric: the grid once per draw, stacked, with that draw's curve inestimate__and its id insample__, as brms lays it out. A maximum-likelihood fit has draws only underband = "boot", where a draw is one refit; with any other band it is refused. It cannot be combined withsurface = TRUE.- select_points
For
plot(points = TRUE):0(the default) draws the observations the faceting section describes. A positive number also drops each observation whose value of a numeric predictor is farther than this from the value the curve holds that predictor at, both scaled to the unit interval over the observed range. brms's argument; the points are in the attribute"points".- too_far
For
surface = TRUE: remove the grid points farther than this from every observation, on the unit square, withmgcv::exclude.too.far().0(the default) keeps all.- data
The original model data. Only needed when the model frame does not store a raw variable (e.g. a variable used only inside
poly()).- int_conditions
Named list giving the values one or both variables of an effect are evaluated at, in place of the defaults (the range of a numeric grid,
mean +/- sdfor a numeric moderator). An element is either the values themselves or a function of the observed column, e.g.int_conditions = list(z = c(-1, 0, 1))orlist(z = function(v) quantile(v, c(0.1, 0.9))). Names on a numeric vector become the moderator'seffect2__labels. brms's argument, with brms's meaning.- categorical
Per-category display for a polytomous family:
TRUE(the default there) draws one curve per response category and keys the effect"x:cats__", as brms'scategorical = TRUEdoes;FALSEdraws the expected CATEGORY NUMBER,sum(k * p_k), which is brms's default. Only for an ordinal or categorical family with nodpar; a nominal family has no ordered categories to average and refusesFALSE.
Value
A named list of data frames (one per effect), in brms's
column layout: the varied variable(s), then every other model
variable at the value it is held at, then cond__ (the condition
label, always present), effect1__ and, for a two-variable effect,
effect2__ (the moderator as a display label: rounded to two
decimals, levels descending), then estimate__, se__ (on the
displayed scale, as in brms), lower__ and upper__. Printing
it draws the plots. A polytomous fit adds a cats__ column, one
block of rows per response category, and keys the effect
"x:cats__".
plot(ce, points = TRUE) overlays the raw observations (the brms
argument), each panel showing only the observations that belong to
its own condition; see the faceting section. No points are drawn
for a per-category ordinal display, a non-mean dpar, or a matrix
response (a message says so).
New rows of a model with me()
A grid row has no latent value. The estimate is the value at the held x,
which
is close to the median of brms's draws, and se__, lower__ and upper__
carry the variance of the draw from N(x, sdx), so they are not coefficient
uncertainty alone. The band is the draw's own quantiles on the response
scale.
A me(gr = ) group is held at NA, as brms holds it, so each grid row is a
level of its own.
With several responses, the panels are in brms's order: the effects outside, over what any response reads, and the responses inside.
Several conditions become one faceted page
A conditions data frame of several rows gives the effect one panel
per row, laid out as small multiples on a SINGLE page with a shared
scale, the way brms's facet_wrap("cond__") does.
plot(ce, ncol = ) sets the number of columns; the default lays the
panels out roughly square, as brms's ncol = NULL does.
The panels are drawn with tinyplot when it is installed, which
supplies the shared axes and a single outer legend. Without it the
fallback is a grid of ordinary base-graphics panels, still one page
and still honoring ncol, labeled by condition on the y axis. The
per-category ordinal display always takes the fallback grid: its
grouping slot already carries the response category.
points = TRUE draws only the observations belonging to each
condition, matching brms's make_point_frame(). A condition claims
the rows of the data that MATCH it on the variables it sets, so with
one condition per level of a factor each observation appears once, in
its own panel. Two rules bound that, both as in brms:
A NUMERIC condition variable is dropped from the match, because a reference value such as
list(x2 = 0.37)is a point on a continuum that names no observation; matching on it would empty every panel. A grouping factor stored as a number is exempt, being a label rather than a continuum. A condition left with nothing to match on therefore claims EVERY observation, and its panel differs from the others only in its curve.A condition variable that names no column of the model data cannot select anything either, so the points are left unsplit and every panel draws all of them.
Unlike brms, a variable the conditions data frame does not set is
not silently pinned to its first level for this purpose, so an
unmentioned factor does not drop observations from every panel.
Ordinal responses
cumulative(), sratio(), cratio() and acat() have no mean, so
the display is per CATEGORY, as brms's categorical = TRUE is: each
effect data frame gains a cats__ factor of the response's own
levels and carries the fitted category probability in estimate__,
with one curve per category in the plot (a second predictor gets a
panel of its own). A one-variable effect is keyed "x:cats__" there,
brms's key for that layout.
That is the DEFAULT here and it is brms's non-default: brms's own
default summarizes the categories into an expected category number
and warns that it is treating an ordered factor as continuous.
categorical = FALSE asks for that summary anyway, sum(k * p_k)
with its own delta-method band (the category weights go on the
gradient, so the covariances between the category probabilities are
kept), keyed "x" and directly comparable with brms's default
curve. It gives brms's warning, "Predictions are treated as
continuous variables", because the display is the one brms warns
about; the default display gives none, because it treats nothing as
continuous.
se__ is then on the probability scale, and the band is a Wald
interval on the logit of the probability so it cannot leave [0, 1].
The standard errors are the delta method over the joint covariance of
the coefficients, the thresholds AND the cs() coefficients: a
category probability depends on all of them, and holding the
thresholds fixed would understate every band.
method = "predict" is refused there (the category probabilities are
already the whole predictive distribution). Naming a distributional
parameter, dpar = "mu", opts back into the ordinary display of the
latent linear predictor.
Confidence bands
band picks how lower__ and upper__ are found. The estimate is
the same curve in all three cases; only the band changes.
"wald"(default, and free): the delta-method standard error, back-transformed from the scale the band is symmetric on. For the ordinary display that scale is the link scale. For the expected response of a family whose mean runs through several distributional parameters (zero inflation, a hurdle,trials(), truncation) the standard error is the delta method over EVERY predictor's coefficients jointly, so the cross-parameter covariances are in the band; the band's scale is then themulink's if the mean lives on it, the log scale if the mean is positive (so the band cannot cross zero), and the response scale otherwise. The two rules agree exactly wherever the mean IS the inverse link ofmu."profile": one likelihood-root search (TMB::tmbroot()) per grid point. A grid point's linear predictor is a linear combination of the coefficients, so the search inverts the likelihood ratio along that combination; the link is monotone, so the two endpoints map through it. The band is not symmetric and does not assume a quadratic log-likelihood, which is what makes it worth its cost near a boundary or at a small sample size."boot": percentiles of the grid predictions across ONE parametric bootstrap of refits, run asfrm_bootstrap()runs it. One bootstrap serves every effect, condition set and ordinal category of the call;attr(ce, "boot")returns it, and passing it back asboot =costs no refits at all. The responses are simulated with every smooth,gp()andhsgp()curve held at its fit, a smooth indexed by a grouping factor included, asfrm_bootstrap()holds them: brms's band is the posterior of the smooth coefficients, not their prior. A group-level term is redrawn fresh, unless the grid reads it at an OBSERVED level (seere_formula): then it is held at its fitted effects too, so that every refit estimates the same group again; responses simulated with fresh effects for it would make the refit's level a different group each time and center the band on the population curve. A term the grid reads at an observed level in some rows and at a new level in others needs both simulations at once, and that call is refused by name;band = "wald"answers it. Draws taken underre_formula = NULLcarry a new group's effects and draws taken without it do not, and draws simulated with a group held are not draws simulated with it redrawn, soboot =refuses either swap by name rather than returning the wrong band.
A Student-t random-effect block enters either band as a GAUSSIAN
with the t variance, nu / (nu - 2) times the scale matrix: the
delta method has no other shape to offer, and the bootstrap draws
the same way so that the two bands stay comparable. It is the right
variance around a heavier-tailed truth, not the right quantile.
se__ is on the displayed scale, as brms's MAD of its draws is. For
"wald" and "profile" it is the delta-method standard error of the
displayed value: the profile changes the endpoints, not the standard
error. For "boot" it is the standard deviation of the bootstrap
draws. The Wald band is symmetric on the link scale, so se__ is not
its half width.
The three bands answer the same question and need not give the same interval. Wald and bootstrap agree in the middle of a grid, and the remaining difference there is the bootstrap's own Monte Carlo error: on a zero-inflated fit the widths differ by 13% at 200 refits and 4% at 800. At the ENDS of a grid where the estimate is poorly determined they need not converge at all: on a steep zero-inflated shape the Wald band stays about 28% wider at 3000 refits, because it is symmetric on its own scale and the percentile band is not. The point estimate is the same curve either way.
Cost, and how it is capped. A root search is two constrained
optimizations, so band = "profile" profiles at most
profile_points (default 25) of a numeric grid, spread over its
range and including both ends, and interpolates the endpoints
linearly between them on the link scale. resolution still governs
the estimate curve. A factor grid is profiled at every level. Points
whose search does not converge become NA and one warning names how
many. band = "boot" costs its refits once, however many effects are
asked for.
Refusals. band other than "wald" needs method = "epred": a
prediction interval is already a simulation quantile. band = "profile" additionally needs the displayed quantity to BE a linear
combination of the parameters, so it is refused (naming "boot") for
an ordinal category probability, for an expected response that runs
through several distributional parameters or through truncation
bounds (dpar = names one predictor and opts back in), for a
nonlinear predictor, for a predictor carrying s(), gp() or
hsgp() (basis coefficients are inner parameters), and for a REML
fit or frmtmb_control(profile = TRUE) (the coefficients are not
outer parameters there).
A nonlinear predictor (nl = TRUE) gets its "wald" band from the
Jacobian of the nonlinear body, which frm_lp_basis() tapes: the
delta method on the link scale, back-transformed, as for a linear
predictor. On y ~ a * exp(b * z) fitted to 150 rows the standard
error agreed with the standard deviation of 20000 curves drawn from
the fit's covariance to within that Monte Carlo error. It is a
first-order
approximation, which is a stronger assumption for a curved body than
for a linear one; band = "boot" makes none. The Wald band is refused
for a nonlinear display that runs through several predictors (the
expected response of a zero-inflated or hurdle family, a reported
mixing weight, the ordinal categories) and at a new level of a term
the displayed predictor itself reads, where the Jacobian of one
predictor is not enough; band = "boot" covers both. band = "profile" stays refused.
The per-category display of a nominal family has no Wald band either,
since its probabilities have no threshold Jacobian to differentiate.
New group levels
Under re_formula = NULL, or a formula that keeps a term, each grid
row reads each group-level term at an observed level or at a new
level (see re_formula). Some terms read a row in their own way:
gr(g, by = f)is one term per level off. A row reads only the term of its ownflevel. Withgunset, the row reads a new level of that term, drawn with the covariance of thatflevel, as brms draws it.mm(g1, g2)has one grouping variable per member. An unset member isNAand reads a new level. Members with the same new value (for example, two unset members) read one new level, and their weights add, as in brms. Members with different unseen values ("99"and"98") read different new levels, each drawn on its own, as two unseen levels of(1 | g)are. brms 2.23.0 gives them one shared draw, because it numbers unseen values per member, not by value. Withband = "boot", a row with one member at an observed level and one at a new level of the same block is refused by name, as are rows that mix the two.mm(g1, g2, by = cbind(f1, f2))is one block per by-level. A member at an observed group reads the block that holds the group, and a new member reads the block of its own by-value, where its new level is drawn with that by-level's covariance. Two new members with the same value and the same by-value read one new level, and their weights add. brms 2.23.0 cannot draw a new level of such a term; it stops.A factor-smooth (
s(x, g, bs = "fs")) or a smooth with abyfactor has no curve for a level that the fit did not see. Whenconditionssets such a factor to an unseen level, or the grid leaves it unset, the call is refused by name. brms also refuses the unseen level.
With band = "boot" and on draws, a new level is drawn as follows.
The rows are predicted at a placeholder level of the term, and the
draw replaces the effects of that level. The placeholder can change
only a grouping column that no other part of the model reads: not a
column of a fixed effect, a smooth, a by variable or a nonlinear
body, and not a column of a term that the same rows read at an
observed level. Two terms that both read a new level in the same rows
can share a placeholder column (for example mm(g1, g2) beside
(1 | g1)), because their effects are separate coefficients. If no
placeholder moves the rows without moving such a column, the rows
keep their columns and the term's level is renamed instead: in a
copy of the fit used for those rows alone, one level of the term
takes the label the rows carry, and the draw replaces its effects.
That is how crossed terms such as (1 | g) + (1 | h) + (1 | g:h)
are drawn when g and h are set to observed levels that the data
never has together: g and h keep their levels, and g:h reads a
new level. With one new level in the call, the band on draws equals
brms's at the same draws and the same seed, with
sample_new_levels = "gaussian" (dev/ceplot-crossed-brms.R); with
several, brms draws level by level and this draw by draw, so the
bands agree in law but not number. A row whose grouping variable is
unset there has no label to rename to, and is refused by name. A
multi-membership member that no
placeholder serves is still refused by name ("cannot draw a new
level of the group-level term"); then set the members in
conditions to levels the fit saw, or use re_formula = NA.
Draws objects
On a frmtmb_draws object from frmtmb.sample::frm_sample() the
same grids are evaluated once per posterior draw, and estimate__,
lower__,
upper__ and se__ are the pointwise median, quantiles and median
absolute deviation of the drawn curves under brms's default
robust = TRUE (the mean and standard deviation under
robust = FALSE). spaghetti = TRUE keeps the curves themselves.
There is no band = or method = to
choose (the band IS the posterior quantile band), a nonlinear
predictor and a nominal per-category display work without a delta
method, and the method runs on formula-route draws that have no
maximum-likelihood fit behind them. ndraws thins the draws
evenly for a cheaper curve. Draws from a sampling run with
laplace = TRUE
are refused: the sampled vector no longer aligns with the model's
parameter template.
Which predictors are plotted by default
Every variable of the selected linear predictor that the display can
vary: its fixed-effect terms, its smooth terms and its mo() terms
(whose design columns are placeholders, so the variable is read from
the term itself). On a nonlinear fit they live one level down - the
covariates the nonlinear formula reads, plus the terms of each
nonlinear parameter's own predictor - and all of those are collected
too. Matrix-valued columns are excluded, a grid over a matrix
covariate not being a curve. Every fitted interaction whose
components are single plottable variables adds an "a:b" display,
as in brms: a fitted interaction hidden by default invites reading
the main-effect curves as the whole story. The display takes two
variables, so a three-way or deeper term contributes its leading
pair, with the remaining variables at their reference values until
conditions = pins them. Naming effects = overrides the search.
A response whose predictor reads mi(x, idx = ) is refused by name.
Such a term reads x on the row whose index() value equals the
row's idx value, and a display grid holds both at one reference
value, so every grid row names the same row. brms 2.23.0 stops on
the same grid. Predict over rows you build, with
fitted(newdata = ).
Examples
set.seed(5)
dd <- data.frame(x = rnorm(120), f = factor(rep(c("a", "b"), 60)))
dd$y <- rnorm(120, 1 + 0.5 * dd$x + (dd$f == "b"), 1)
fit <- frm(bf(y ~ x * f), family = gaussian(), data = dd)
ce <- conditional_effects(fit, effects = c("x", "x:f"))
plot(ce, ask = FALSE)
# prediction intervals instead of epred bands
ce_p <- conditional_effects(fit, effects = "x", method = "predict")
# \donttest{
# a likelihood-profile band: asymmetric, and no quadratic assumption
ce_pr <- conditional_effects(fit, effects = "x", band = "profile",
resolution = 20, profile_points = 5)
# a bootstrap band, reused for a second effect without refitting
ce_b <- conditional_effects(fit, effects = "x", band = "boot",
boot = 25, seed = 1)
ce_b2 <- conditional_effects(fit, effects = "x", band = "boot",
boot = attr(ce_b, "boot"))
# }