Skip to contents

posterior_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_draws from frm_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 (and allow.new.levels) and sample_new_levels. allow_new_levels = FALSE, and TRUE with levels the fit saw, answer as the call without it does. A level the fit did not see, in a term re_formula keeps, is refused with or without the flag, and so is a newdata that leaves the grouping column out under TRUE: 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, and re_formula = NA predicts here at the population level.

newdata, resp

As in frmtmb::predict.frmtmb_fit(). A model with one response does not read resp, as in brms. An empty resp is every response.

re_formula

The random-effect switch, in brms's spelling: NULL (the default) conditions on each draw's own random effects, NA or ~0 gives the population-level quantity. Its meaning is frmtmb::predict.frmtmb_fit()'s re_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 for posterior_epred(). The default is the family's mu.

nlpar

The parameter an nlf() body names. brms keeps it apart from dpar; frmtmb asks for either by the dpar name, 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 ndraws takes. Give one or the other.

sort

brms's argument. Rows come back in the order of the data here, always, so sort = TRUE is 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, repeated ndraws_point_estimate times. It is a parameter-space operation and not a summary of the output, as in brms.

transform

For posterior_linpred(): if TRUE, apply the inverse link (the value of the mu dpar on its natural scale, brms's convention; unlike posterior_epred() this is not the response mean for zero-inflated and similar families).

incl_thres

For posterior_linpred() on an ordinal family: TRUE includes the thresholds, as in brms. The result is then a draws by observations by thresholds array whose layer k is disc * (thres_k - mu) for cumulative() and sratio() and disc * (mu - thres_k) for cratio() and acat(), with a cs() term's part added to mu at each threshold. Under thres(gr = ) a row reads its level's thresholds and is NA past them. As in brms it is ignored when dpar or nlpar is given, under transform = 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 times 1 - hu there, 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
# }