Expected-value and predictive draws from sampled parameters
Source:R/methods-draws.R
posterior_epred.Rdposterior_epred() evaluates the response-scale expectation per
draw; posterior_predict() additionally simulates responses from
the family, giving the posterior predictive distribution. Both
condition on each draw's own random effects (re_formula = NA drops
them; re.form is an accepted alias here, see Argument
spellings).
Usage
posterior_epred(object, ...)
# S3 method for class 'frmtmb_draws'
posterior_epred(
object,
newdata = NULL,
re_formula = arg_unset(),
re.form = arg_unset(),
resp = NULL,
dpar = NULL,
nlpar = NULL,
ndraws = NULL,
draw_ids = NULL,
sort = FALSE,
point_estimate = NULL,
ndraws_point_estimate = 1,
...
)
posterior_linpred(object, transform = FALSE, ...)
# S3 method for class 'frmtmb_draws'
posterior_linpred(
object,
transform = FALSE,
newdata = NULL,
re_formula = arg_unset(),
re.form = arg_unset(),
resp = NULL,
dpar = NULL,
nlpar = NULL,
incl_thres = NULL,
ndraws = NULL,
draw_ids = NULL,
sort = FALSE,
point_estimate = NULL,
ndraws_point_estimate = 1,
...
)
posterior_predict(object, ...)
# S3 method for class 'frmtmb_draws'
posterior_predict(
object,
newdata = NULL,
re_formula = arg_unset(),
re.form = arg_unset(),
transform = NULL,
resp = NULL,
negative_rt = FALSE,
ndraws = NULL,
draw_ids = NULL,
sort = FALSE,
ntrys = NULL,
cores = NULL,
point_estimate = NULL,
ndraws_point_estimate = 1,
...
)Arguments
- object
A
frmtmb_drawsfromfrm_sample().- ...
Refused: an argument the method does not have is an error naming it, rather than a silently ignored name. The exceptions are brms's
allow_new_levels(andallow.new.levels) andsample_new_levels.allow_new_levels = FALSE, andTRUEwith levels the fit saw, answer as the call without it does. A level the fit did not see, in a termre_formulakeeps, is refused with or without the flag, and so is anewdatathat leaves the grouping column out underTRUE: brms draws that level's effect from each posterior draw, which is not built here, and predicting it at the population level would drop the group variance from every draw.frmtmb::predict.frmtmb_fit()predicts unseen levels from the maximum-likelihood fit, andre_formula = NApredicts here at the population level.- newdata, resp
As in
frmtmb::predict.frmtmb_fit(). A model with one response does not readresp, as in brms. An emptyrespis every response.- re_formula
The random-effect switch, in brms's spelling:
NULL(the default) conditions on each draw's own random effects,NAor~0gives the population-level quantity. Its meaning isfrmtmb::predict.frmtmb_fit()'sre_formula; see Argument spellings.- re.form
lme4's spelling of
re_formula, accepted on the four methods where brms accepts it too. Pass one or the other, not both.- dpar
Which distributional parameter to evaluate: its linear predictor for
posterior_linpred(), its response-scale value forposterior_epred(). The default is the family'smu.- nlpar
The parameter an
nlf()body names. brms keeps it apart fromdpar; frmtmb asks for either by thedparname, so this is the same setting and the slot is here for brms's position.- ndraws
Number of draws to use (default: all).
- draw_ids
The draws to use, by row index, instead of the evenly spaced subsample
ndrawstakes. Give one or the other.- sort
brms's argument. Rows come back in the order of the data here, always, so
sort = TRUEis refused by name.- point_estimate, ndraws_point_estimate
brms's arguments, which collapse the draws to their
"mean"or"median"FIRST and run the method once at that one parameter vector, repeatedndraws_point_estimatetimes. It is a parameter-space operation and not a summary of the output, as in brms.- transform
For
posterior_linpred(): ifTRUE, apply the inverse link (the value of themudpar on its natural scale, brms's convention; unlikeposterior_epred()this is not the response mean for zero-inflated and similar families).- incl_thres
For
posterior_linpred()on an ordinal family:TRUEincludes the thresholds, as in brms. The result is then a draws by observations by thresholds array whose layerkisdisc * (thres_k - mu)forcumulative()andsratio()anddisc * (mu - thres_k)forcratio()andacat(), with acs()term's part added tomuat each threshold. Underthres(gr = )a row reads its level's thresholds and isNApast them. As in brms it is ignored whendparornlparis given, undertransform = TRUE, and on a family that is not ordinal.hurdle_cumulative()is refused, a divergence the user decided on 2026-10-06: brms returns the hurdle probability beside the threshold predictors times1 - huthere, which is the linear predictor of nothing. An ordinal mixture is refused, in brms's words: "'incl_thres' is not supported for mixture models."- negative_rt
For
posterior_predict(): refused. It is brms's sign convention for its own wiener family.- ntrys, cores
brms's arguments, carried so that a positional brms call lands where brms lands it. Both are refused by name: the rejection limit of a
trunc()ed draw is the family simulator's own, and the draws are replayed in one process.
Value
A draws-by-observations matrix; for a categorical outcome
posterior_epred() returns a draws-by-observations-by-categories
array (see the section below). On a multivariate model asked for
every response (resp = NULL) or for several, a
draws-by-observations-by-responses array; see Multivariate
models.
Categorical outcomes
An ordinal family predicts a DISTRIBUTION per observation, not one
number: each draw's frm_linpred(type = "response") is an n x K
matrix of category probabilities. Those stack into a 3-D
draws x observations x categories array. dimnames are
list(NULL, <observation names or NULL>, <category levels>), so
ep[, , "high"] is the draws-by-observations matrix for one
category and ep[k, , ] is draw k's own n x K prediction, the
matrix frm_linpred(type = "response") returns. Every ep[k, i, ]
sums to 1 for an ordinal family.
This is brms's convention: ?brms::posterior_epred.brmsfit
documents "an S x N x C array" for categorical and ordinal models
and an S x N matrix otherwise, and frmtmb follows brms spelling for
brms-origin functions. Any family whose per-draw response-scale
prediction is a matrix takes the array shape; every family that
predicts one number per observation keeps the plain
draws x observations matrix.
posterior_predict() is unaffected for an ordinal or categorical
family: it draws one category per observation. posterior_linpred()
with no dpar gives every location predictor of a family whose
parameters run over categories (categorical, multinomial and the
simplex families) or of a mixture, as brms does: a draws x observations x predictors array with no dimnames, K - 1 layers
with a reference category and K without one. dpar = "mub" gives
one predictor's draws x observations matrix. On these families
transform = TRUE needs a dpar, as in brms. What does take the
array shape in posterior_predict() is a
matrix-valued RESPONSE: frmtmb::multinomial() counts, frmtmb.latent::mixture_mvn()
draws and frmtmb.latent::lca() item codes give one row per observation, so the
draws stack into draws x observations x columns.
Structured draws
posterior_predict() uses the same simulator simulate() does,
including the structured families (frmtmb.latent::hmm(), mixture(groups = ),
frmtmb.latent::mixture_mvn()) and residual correlation terms; see the Structured
draws section of frmtmb::simulate.frmtmb_fit(). A structured family indexes
the rows the model was fitted on, so newdata is refused for it. A residual
correlation term is drawn on the groups and times of newdata.
Argument spellings
One rule decides every name in this package: where lme4 or glmmTMB
and brms disagree, brms wins. The random-effect switch is therefore
re_formula everywhere, on the draws methods here and on
frmtmb::predict.frmtmb_fit() and
frmtmb::simulate.frmtmb_fit() alike; lme4's re.form was dropped
from the fit surface and is refused there by name.
Five methods take BOTH spellings, and they are exactly the five
where brms ITSELF accepts both. Four declare them:
posterior_epred(), posterior_linpred(), posterior_predict()
and predictive_error() carry re_formula and re.form side by
side on brmsfit. The fifth does not declare them and accepts them
anyway: predictive_interval.brmsfit()'s whole body is
posterior_predict(object, ...), so the alias reaches a formal one
frame down. What brms ACCEPTS is the test, not what it declares.
pp_check() is the one method that lost the alias, and the same
test is why it stays lost. brms DOES honor re.form there, through
the same dots forwarding, but it warns "unrecognized and ignored"
while doing it. Matching brms means matching what brms decided, and
a warn-then-honor path is a leak rather than a decision: the
argument changes the answer and the message says it did not.
predictive_interval() is the contrast, where brms honors the alias
silently and this package follows.
Giving both at once is refused rather than resolved. Two names for one setting supplied together is a question about what was meant, and guessing at it would silently ignore one of them.
The argument ORDER is brms's too, so a positional brms call means
the same thing here: newdata then re_formula then re.form then
resp, after transform in posterior_linpred() and before it in
posterior_predict().
The literal default of both formals is an internal "not supplied"
marker rather than a value, because NULL (keep the random effects)
and NA (drop them) are both real settings here and neither can
double as "unset". The behavior when neither is given is unchanged:
NULL on every draws method, NA on pp_check() for a fit.
New rows of a model with me()
A new row has no latent value, so each posterior draw draws one from
normal(x, sdx), per row, or per level under me(gr = ), as brms does.
newdata must hold sdx, and corme is not read. Two responses or two
dpars
that read one term read one latent value per draw, a stated divergence: brms
draws one per predictor, against its own Stan program, which has one
Xme_1, and
at the training rows of a two-response fit the residuals correlate at 0.734,
one
latent predicts 0.739 and brms's replicates give -0.001. Without new data,
the
latent values are the draws' own.
Multivariate models
Without resp, the three methods answer for every response of a
multivariate model, as brms does: a draws x observations x responses
array whose third margin carries brms's response names (ya for a
column y_a). resp takes one response, which gives its matrix, or
several, which give their layers in the order named. Either spelling
of a name is accepted; a name given twice is refused, as brms refuses
it, and an empty resp is every response, as in brms. Under
set_rescor(TRUE) a resp out of the model's order is answered with
the correlations in the order named, where brms 2.23.0 stops. A
response that predicts several values per row (the category
probabilities of an ordinal response in posterior_epred()) has no
layer in this layout: name it with resp.
With set_rescor(TRUE), posterior_predict() draws the responses
of a row JOINTLY, as brms's posterior_predict() does: per draw, a
multivariate normal with covariance
\(\mathrm{diag}(\sigma) R \, \mathrm{diag}(\sigma)\), where
\(R\) is the draw's residual correlation matrix and \(\sigma\)
the row's residual standard deviations (which a formula for sigma
makes vary by row), or for student() the multivariate t with the
one shared nu. So a sum or a contrast of the responses, or a joint
interval, carries the residual correlation. With several responses
named, the draw is joint over those, with the correlations among
them. With one response named, the draw is that response's margin:
normal, or t with the shared nu. brms 2.23.0 draws that margin of a
student() model with nu = 1, which is not the margin of its own
model; this package uses the shared nu. Without rescor, the
responses are independent given a draw's parameters, and each layer
is drawn on its own.
Laplace draws
Draws from frm_sample(laplace = TRUE) hold no group-level
coefficients, smooth coefficients or
mi() values. A call that reads them is refused by name, and a
call that does not, such as re_formula = NA on a model whose only
integrated values are group-level coefficients, is computed from
the draws exactly. See the Laplace draws section of frm_sample().
Examples
# \donttest{
if (requireNamespace("tmbstan", quietly = TRUE) &&
requireNamespace("rstan", quietly = TRUE) &&
!frmtmb.sample:::tmbstan_build_broken()) {
set.seed(9)
dd <- data.frame(x = rnorm(80), g = factor(rep(1:8, 10)))
dd$y <- rpois(80, exp(0.3 + 0.4 * dd$x + rnorm(8, 0, 0.5)[dd$g]))
fit <- frm(bf(y ~ x + (1 | g)) + poisson(), data = dd)
ds <- frm_sample(fit, chains = 1, iter = 500, refresh = 0)
nd <- data.frame(x = c(-1, 0, 1),
g = factor(1, levels = levels(dd$g)))
# the expected response per draw: uncertainty in the mean
ep <- posterior_epred(ds, newdata = nd)
apply(ep, 2, quantile, c(0.025, 0.5, 0.975))
# the predictive distribution adds the family's own noise, so its
# intervals are wider
pp <- posterior_predict(ds, newdata = nd)
apply(pp, 2, quantile, c(0.025, 0.5, 0.975))
# the linear predictor itself, on the link scale by default
head(posterior_linpred(ds, newdata = nd, ndraws = 5))
}
#> frm_sample(): default priors (brms 2.23 defaults; prior = "flat" puts brms's (flat) in every slot)
#> Intercept student_t(3, 0, 2.5)
#> sd student_t(3, 0, 2.5) [natural sd scale]
#> b (flat), as brms leaves slopes
#> Warning: Bulk Effective Samples Size (ESS) is too low, indicating posterior means and medians may be unreliable.
#> Running the chains for more iterations may help. See
#> https://mc-stan.org/misc/warnings.html#bulk-ess
#> Warning: Tail Effective Samples Size (ESS) is too low, indicating posterior variances and tail quantiles may be unreliable.
#> Running the chains for more iterations may help. See
#> https://mc-stan.org/misc/warnings.html#tail-ess
#> [,1] [,2] [,3]
#> [1,] 0.38336326 0.73137207 1.07938088
#> [2,] -0.29968714 0.09276241 0.48521196
#> [3,] -0.25565944 0.10586192 0.46738327
#> [4,] 0.08473788 0.46377053 0.84280319
#> [5,] -0.47892791 -0.19427159 0.09038472
# }