Skip to contents

Builds prior specifications with brms spelling: set_prior("normal(0, 5)", class = "b"). Combine several with + or c(). Distributions: normal(mu, sd), student_t(df, mu, sd), cauchy(mu, sd), exponential(rate), logistic(mu, s), gamma(shape, rate), inv_gamma(shape, scale), beta(a, b), uniform(lb, ub), lognormal(mu, sd), lkj(eta), dirichlet(alpha); an empty string sets bounds only.

Usage

set_prior(
  prior = "",
  class = "b",
  coef = "",
  group = "",
  resp = "",
  dpar = "",
  nlpar = "",
  lb = NA,
  ub = NA
)

Arguments

prior

Distribution string, e.g. "normal(0, 5)", or a prior_normal()/prior_t()/prior_lkj() object, or "" for bounds only.

class

"b", "Intercept", "sd", "sds", "cor", "theta", one of the residual-structure classes "ar", "ma", "cosy", "cortime" and "rescor", the simplex classes "simo" and "sbhaz", the me() classes "meanme", "sdme" and "corme", or a distributional parameter's own name ("sigma", "shape", ...). See A distributional parameter's own class.

coef

Restrict to one coefficient (classes "b"/"Intercept"), to the standard deviation of one coefficient (class "sd", with group), to one smooth term (class "sds"), name the simplex of class "simo", name one me() variable of class "meanme" or "sdme", or name one internal parameter of class "theta". A coefficient is named as brms names it and as default_prior() lists it: logxp for the column of log(xp), IxE2 for I(x^2). The name of the design column, log(xp), also works.

group

Restrict class "sd" or "cor" to one grouping factor, or class "corme" to the me() terms of one gr = variable.

resp

Response of a multivariate model. Required there for every class except "cor", "rescor", "theta" and the me() classes; refused on a model with one response and on classes "rescor", "meanme", "sdme" and "corme".

dpar

Distributional parameter (default: the location parameters).

nlpar

Nonlinear parameter of an nl = TRUE formula. See Nonlinear parameters.

lb, ub

Optional hard bounds, on the scale described in Hard bounds.

Value

A frmtmb_priorlist.

Details

Classes and their scales:

  • "b": population-level coefficients of dpar (default: the location parameters), excluding the intercept; narrow to one coefficient with coef. Link scale.

  • "Intercept": the intercept of dpar, at the MEAN of that sub-formula's predictors, which is the intercept brms's own Intercept prior constrains. Link scale. See Where an intercept prior lands. On an ordinal family the thresholds are the intercept, here as in brms, so this class addresses the whole threshold vector; see Ordinal thresholds.

  • "sd": random-effect standard deviations, on the NATURAL sd scale with the log-Jacobian applied, so set_prior("exponential(1)", class = "sd") means what it says; narrow with group, and to one coefficient's standard deviation with group and coef (coef = "x" for the x column of (1 + x | g), as default_prior() lists it). See Group-level standard deviations. As in brms, resp, dpar and nlpar select the standard deviations of that response, distributional parameter and nonlinear parameter only, and leaving one empty selects the empty one: with no dpar the specification reaches the location parameter's blocks and not a phi ~ (1 | g) block, and in a multivariate model a specification with no resp reaches nothing and is refused. A block that spans several predictors, (1 | q | g) in both mu and sigma, is the one exception, as it is in brms: there a specification that leaves a field empty reaches every standard deviation of the block, and a more specific one takes over its own.

  • "cor": the CORRELATION of a random-effect block, as a whole. lkj(eta) only, and it addresses a BLOCK the way class "sd" does, by group; set_prior("lkj(2)", class = "cor") covers every correlated block of the model, which is brms's spelling. See The LKJ prior below.

  • "ar", "ma", "cosy", "cortime": the R-side residual correlation of an ar(), ma(), arma(), cosy() or unstr() term, under brms's own class names. "ar", "ma" and "cosy" take an ordinary density on the NATURAL coefficient with that map's Jacobian applied, as class "sd" does; "cortime" takes lkj(eta) on an unstr() time correlation as a whole. Narrow to one response with resp. See Residual correlation below.

  • "rescor": the residual correlation BETWEEN responses of a multivariate model (set_rescor(TRUE)), as a whole. lkj(eta) only, as brms spells it, and no resp.

  • "lncor": the correlation matrix of the log ratios of a logistic_normal() response with three or more categories, as a whole, brms's class of the same name. lkj(eta) only.

  • "delta": the distance between neighboring thresholds of an ordinal family with threshold = "equidistant", brms's class of the same name, on its own scale; group selects the vector of one level of thres(gr = ). See Ordinal thresholds.

  • "simo": the simplex of one mo() term, dirichlet(alpha) only, addressed by brms's coef: the term's label with 1 appended ("mox1", "mox:fb1", as get_prior() lists them), and by dpar for a term outside the location parameter. alpha is one number or one per weight. On a MAP fit the density carries the Jacobian of the coordinates the simplex is held in, so the mode under dirichlet(a) is the mode of dirichlet(a + 1/2) on the weights, pulled further toward the uniform simplex; see "Monotonic effects" in frm().

  • "sbhaz": the baseline-hazard simplex of a cox() response (frmtmb.survival), or the simplex a family declares under that name (frmtmb_family(simplex_pars =)); dirichlet(alpha) only, brms's class of the same name; no coef.

  • "meanme", "sdme", "corme": the hyperparameters of the latent values of me() terms, brms's classes of the same names. "meanme" is a density on the latent mean, "sdme" one on the latent standard deviation itself, with the log-Jacobian of the log map, as class "sd". coef names one me() variable as default_prior() lists it ("mex" for me(x, sdx)), and neither class takes a group. "corme" takes lkj(eta) on the correlation matrix of the me() terms that share a gr =, as a whole: group selects the gr = variable, and no coef. The three take no resp, dpar or nlpar, because one set of latent values serves the whole model.

  • "theta": frmtmb's own class, for the internal covariance parameters that no brms class names, on the internal scale: a toep() correlation, the parameter of a covariance structure an extension registers (a car() dependence), and a residual term's parameter without an interval. coef names one by its internal name ("theta_12", "thetaac_1"), as default_prior() lists it; with no coef the class covers every random-effect parameter of that kind. A parameter that a class reaches has that class as its one slot, as in brms, which has no class "theta": a standard deviation ("sd", "sdgp"), a gp() length scale ("lscale"), a correlation an LKJ density fits ("cor"), a residual correlation ("rescor", "ar", "ma", "cosy", "cortime", frmtmb.spatial's "lagsar"), the SD of a latent residual ("sderr"). Its internal row is not listed, and a class "theta" prior on it is refused with the class to use.

  • a DISTRIBUTIONAL parameter's own name ("sigma", "shape", "phi", "zi", "nu", ...): a density on that parameter ITSELF, on its NATURAL scale, with the inverse link's log-Jacobian applied, so set_prior("student_t(3, 0, 2.5)", class = "sigma") means what it says. Available where the parameter has no predictor of its own; see A distributional parameter's own class.

In a MULTIVARIATE model, every specification of class "b", "Intercept", "sd", "ar", "ma", "cosy" or "cortime", and every distributional parameter's own class, names its response with resp. A specification without resp is refused, as brms refuses it: write one specification per response. Classes "rescor" and "theta" take no resp, and "cor" needs none. On a model with ONE response, resp is refused, as in brms.

Two spellings are frmtmb's own, and brms refuses both: "cor" with resp, which narrows the prior to that response's blocks, and "Intercept" with nlpar, which is stored as brms's slot of the same parameter, class "b" with coef = "Intercept" and that nlpar (see Nonlinear parameters). A centered intercept has one slot, class "Intercept": class "b" with coef = "Intercept" there is refused, as brms refuses it. A class "b" specification that reaches no coefficient, because the predictor it names has no population-level slope (y ~ 1), is refused, as in brms. In the same way, a class "b" or "Intercept" specification on a NONLINEAR location names its nonlinear parameter with nlpar; see Nonlinear parameters. And where a family's location is SEVERAL distributional parameters, as in categorical(), multinomial() and mixture(), a class "b", "Intercept" or "sd" specification names one of them with dpar ("mub", "mu1"), and default_prior() lists the rows that way, as brms does.

Two specifications for the same slot (the same class, coef, group, resp, dpar and nlpar) are refused wherever a prior is passed in, as brms refuses them; that includes a density followed by a bounds-only specification, so write the density and its bounds in one call. When specifications for DIFFERENT slots reach the same parameter, the more specific one applies whatever order they are written in, as in brms: a coef specification over its class, and a group specification over a class-wide "sd" or "cor" one. No parameter has two classes: each is reached by one class, and the other spelling is refused, so the order between classes decides nothing. lb/ub become hard bounds. See Hard bounds.

Group-level standard deviations

set_prior(class = "sd", group = "g", coef = "x") puts the density on one standard deviation: that of the x column of the g block. brms puts the same prior on sd_g__x. The other standard deviations of the block keep the prior of the group or of the class. A coef without a group is refused, because brms has no such row.

The density is on the standard deviation itself, with the log-Jacobian of the log map. frmtmb holds a correlated block as log standard deviations and separate correlation parameters. It does not hold a Cholesky factor. So each standard deviation is one parameter, and the prior on it is exact. The prior does not change the correlations. A class "cor" prior addresses those. In a Student-t block (gr(g, dist = "student")), the parameter is the scale. That is also what brms's sd is in that term.

Some structures give their columns one shared standard deviation, for example homdiag(), ar1() and homcs(). They have no standard deviation per coefficient. A coef that names one of their columns is refused by name. Drop the coef to put the prior on the shared standard deviation. A block of another response, distributional parameter or nonlinear parameter does not cause this refusal.

The group labels are brms's. A nested (1 | g1/g2) has the groups g1 and g1:g2. A multi-membership (1 | mm(m1, m2)) has the group mmm1m2. default_prior() lists them so.

Where an intercept prior lands

brms centers its design matrix and constrains the intercept at the MEAN of the predictors, recovering the reported one as b_Intercept = Intercept - dot_product(means_X, b). frmtmb parameterizes by the intercept at zero and evaluates a class "Intercept" density at b0 + means_X'b, so the two packages constrain the same quantity. The map between the two parameterizations is unit triangular and carries no Jacobian.

This matters whenever a predictor is not centered. On Reaction ~ Days, where mean(Days) is 4.5, the intercept at zero is strongly correlated with the slope and the intercept at the mean is orthogonal to it, so a prior on the first biases the slope and a prior on the second does not. Earlier releases used the intercept at zero, and brms::get_prior()'s own default there moved the slope by 0.068 standard errors; it now moves it by 0.00003.

Every sub-formula with an intercept is centered separately, as brms does (means_X, means_X_sigma, ...). A NONLINEAR parameter's sub-formula is not centered on either side, and neither are a smooth's unpenalized columns or a mo() term, which sit outside brms's Xc as well. To put a density on the intercept at zero, name it as a coefficient instead: class = "b", coef = "Intercept". A formula written 0 + Intercept + x, or bf(center = FALSE), makes that the intercept's only prior slot, as brms does: the intercept is then class "b" and a class "b" prior without a coef reaches it too, while class "Intercept" has no slot and is refused.

Ordinal thresholds

cumulative(), sratio(), cratio() and acat() have no intercept column: the thresholds replace it. brms priors them as its Intercept class and so does frmtmb, so set_prior("student_t(3, 0, 2.5)", class = "Intercept") on an ordinal model addresses the whole threshold vector. It addresses the THRESHOLDS, at the mean of the predictors (at zero under bf(center = FALSE), as in brms), with the log-Jacobian of the map from frmtmb's internal storage. cumulative() holds (tau_1, log increments), which is the same map Stan's ordered type applies to brms's ordered thresholds. sratio(), cratio() and acat() hold the thresholds themselves, which brms declares as an unconstrained vector, so there is no Jacobian. lb/ub are refused there, because one number cannot box a whole vector of thresholds.

One threshold is addressed by its number, as brms lists it: set_prior("normal(0, 1)", class = "Intercept", coef = "2") is a density on the second threshold, and it replaces a class-wide density there and only there. The vector stays one entry, so the log-Jacobian of cumulative()'s map enters once. Under thres(gr = ) a threshold is named by its level and its number, group = "a", coef = "2". brms has no per-threshold parameter under threshold = "equidistant", and the row is refused there, as in brms.

The threshold structure changes what class "Intercept" addresses, as it does in brms. Under threshold = "equidistant" it is the first threshold alone, at the mean of the predictors, and class "delta" is the distance between thresholds: on delta itself, with the log-Jacobian of the log that cumulative() and hurdle_cumulative() hold it on, since brms bounds it below by 0 there. Under threshold = "sum_to_zero" class "Intercept" is refused: brms's prior there is on thresholds it declares before centering them, whose common location only that prior places, and frmtmb estimates the centered thresholds directly, so the parameter does not exist.

Hard bounds

lb/ub are how a box constraint is written. A specification may carry bounds alone (prior = ""), a distribution alone, or both. A bounds-only specification for a slot another specification already gives a density is refused as a duplicate, as in brms; a bound on a coefficient beside a class-wide density is a different slot and boxes that coefficient under the class density.

A bound is addressed exactly like the distribution beside it, so set_prior("", nlpar = "guess", lb = 0, ub = 1) bounds the nonlinear parameter guess, and dpar, resp, group and coef narrow a bound the same way they narrow a density. As with a distribution, class "b" with nlpar covers EVERY coefficient of that parameter; coef picks out one.

A bound on one coefficient is frmtmb's own on frm(), a box on the maximum-likelihood fit. brms refuses it ("Prior argument 'coef' may not be specified when using boundaries."), and so does frmtmb.sample::frm_sample(), which samples brms's model: there a bound goes on the class row.

The scale is the parameter's own: class "sd" bounds a standard deviation on the sd scale (frmtmb stores its log), classes "ar", "ma" and "cosy" bound the natural coefficient of a residual structure, and class "theta" bounds an internal covariance parameter itself, one position at a time with coef = "theta_12", where no class reaches that parameter (see class "theta" above). A correlation takes no bound, as in brms: a correlation matrix's entries are not free of one another, and brms writes a Stan program that does not parse for lb on class "cor". Everything else is bounded on the internal (link) scale, so a bound on a log-linked dispersion is a bound on its logarithm.

In frm() a bound is a box constraint handed to the optimizer; in frmtmb.sample::frm_sample() it becomes one of Stan's constrained transforms. Both take this spelling and no other: the lower/upper arguments of releases before 0.49 are gone rather than aliased, and a call still using them fails as an unused argument. Every outer parameter they could reach has a class here, down to a single internal covariance parameter.

Where the two spellings differed, this one broadcasts: a bound carried by nlpar = covers every coefficient of that parameter, the way a prior does, and coef narrows it to one. When a class-wide and a coefficient-specific specification both bound a parameter, the coefficient-specific one applies.

Residual correlation

On a family with no residual y - mu these terms are brms's latent residuals (frmtmb-autocor), and class "sderr" is the standard deviation of the latents, written and carried as class "sd" is. Their coefficients take the classes below, on brms's intervals: (-1, 1) on ar and ma, each entry on its own under cov = FALSE, and (0, 1) on cosy.

frmtmb holds an ar(), ma(), arma(), cosy() or unstr() residual block in one unconstrained vector, chosen so the optimizer cannot step outside the stationary and invertible region. A prior is still written about the parameter brms names, and carried onto that vector with the log Jacobian of the map, exactly as class "sd" carries a density on a standard deviation onto its logarithm. So set_prior("normal(0, 0.5)", class = "ar") is a density on the AR coefficient itself, and summary() reports the parameter the prior was written about.

Bounds behave the same way where the map allows it. A first-order ar, ma or cosy coefficient is a monotone function of one internal parameter, so lb/ub map exactly onto a box. At order two and above they do not: ar[1] is a function of every internal parameter of the block at once, so no box in internal space is the box asked for, and lb/ub are refused rather than approximated. Little is lost, because the parameterization already guarantees stationarity and invertibility, which is what such a bound is usually for, and brms's cov = TRUE form is of order one only. Under cov = FALSE the coefficients are unconstrained and are the internal parameters, so lb/ub apply at any order, as in brms. A bound at an end of the parameter's own interval, such as brms's lb = -1 on a first-order ar, bounds nothing and is accepted, so a default_prior() table can be passed back as prior =.

cosy is bounded below at -1/(d - 1) for d time points, where a compound-symmetric matrix stops being positive definite, and a bound outside that window is refused rather than clamped. brms bounds cosy on [0, 1] instead, so a negative estimate here has no brms counterpart. frmtmb.sample::frm_sample() samples cosy on brms's [0, 1]: its default prior there is brms's flat one, and a cosy prior that sets no lb keeps lb = 0, as brms keeps the bound it declares. default_prior(route = "sample") lists that interval, and the default route lists frm()'s window.

Under a cov = TRUE ar(), ma() or arma(), sigma is the innovation sd, as in brms (frmtmb-autocor). So a prior on class "sigma", its lb and ub, and under sigma ~ x a prior on the intercept of sigma (class = "Intercept", dpar = "sigma", the log innovation sd), are brms's priors on the same parameter.

The LKJ prior

lkj(eta) is the density det(C)^(eta - 1) over a block's correlation matrix C, normalized: eta = 1 is uniform over correlation matrices, larger eta concentrates toward the identity. frmtmb holds a correlation as an unconstrained row-normalized Cholesky parameter rather than as C, so the density is carried onto those parameters with the exact Jacobian of that map (the derivation is in the source of R/priors.R; tests/testthat/test-lkj.R checks the sampled correlations against the closed-form LKJ marginals). The prior a FLAT correlation parameter carries instead is (1 - rho^2)^(-3/2), which is improper.

It fits us() and gr(cov = ) blocks of two or more terms, which hold a whole correlation matrix, and the one-parameter structures cs(), ar1() and hetar1(), whose single bounded correlation takes the LKJ marginal (1 - rho^2)^(eta - 1) with that structure's own Jacobian. A cs() correlation is bounded below at -1/(d - 1), where a compound-symmetric matrix stops being positive definite, and the density is renormalized over that window. toep() is refused: its parameterization is not positive definite everywhere, so it has no correlation matrix to put a density on.

Nonlinear parameters

nlpar addresses one parameter of an nl = TRUE formula, brms's spelling: set_prior("normal(5000, 1000)", nlpar = "ult"), or prior(normal(5000, 1000), nlpar = "ult"). Class "b" there covers EVERY coefficient of that parameter, its intercept included, because a nonlinear parameter's sub-formula is not centered and brms holds its intercept in the same coefficient vector as its slopes. That is why the vignette spelling above lands on ult_(Intercept) rather than on nothing. Narrow to one column with coef ("Intercept" and "(Intercept)" both name the intercept), or write class = "Intercept", nlpar = "ult", which frmtmb stores as that same slot, class "b" with coef = "Intercept", so the two spellings are one slot; brms does not take the second. nlpar narrows classes "sd" and "cor" to the random-effect blocks of that parameter as well.

A class "b" or "Intercept" specification without nlpar does not reach a nonlinear parameter. On a model whose location is nonlinear, such a specification addresses no parameter, and it is refused, as in brms. A distributional parameter keeps its own spelling there: set_prior("student_t(3, 0, 2.5)", class = "sigma") needs no nlpar.

A prior with a location places frm()'s start for a nonlinear parameter. normal(), student_t() and cauchy() all carry one, and where start does not set a nonlinear coefficient, that coefficient begins at the prior's location, reported in a message. Other parameters keep their usual starts: a prior is a penalty, not a claim about where to begin. Without a located prior a nonlinear model still needs start, because frm() evaluates the objective AT the starting values; par_template() names them.

resp picks one response of a multivariate model, and a nonlinear parameter of one response is addressed with both resp and nlpar.

Translating a brms prior

frm(prior = ) takes a brmsprior object directly, whether it came from brms::set_prior(), brms::prior() or brms::get_prior(). A row applies whatever its prior string says, which is brms's own rule; an empty string is brms's flat default and applies nothing. The source column is not read. Earlier releases dropped rows marked source == "default" were dropped, which lost a prior the user had edited into a get_prior() table in place, because brms does not update source after that edit.

A specification means here what the same words mean in brms. Every class brms writes that frmtmb can honor is a class set_prior() takes under the same name and with the same meaning, so a table and a hand-written specification reach one code path:

  • b, Intercept, sd, cor, ar, ma, cosy, cortime and rescor are frmtmb's own class names and keep their meaning.

  • a DISTRIBUTIONAL parameter's own class (sigma, shape, phi, nu, kappa, sigma1, ...) is a density on that parameter ITSELF, through the dpar's inverse link with that map's log-Jacobian, which is the change of variables class "sd" performs. A bound travels with it, so lb = 0 on a log-linked dispersion becomes no constraint rather than a floor of 1.

  • simo and sbhaz keep their meaning too: a dirichlet() on a mo() simplex and on a cox() baseline. So do meanme, sdme and corme, the hyperparameters of a me() term, brms's lkj(1) default on corme included.

  • sds is the standard deviation of a smooth's penalized part, brms's class of the same name. coef names one smooth term as default_prior() lists it ("s(x)", "t2(x, z)", "s(x, by = f)"), and a term with several standard deviations (a t2() or a by-smooth) takes the density on each of them, as in brms. Class "sd" does not reach a smooth.

  • theta/theta1/theta2, sdcar and car are refused by name, each saying where frmtmb keeps that quantity instead. A refusal is deliberate: translating one of them would produce a different model rather than no model.

  • a coef on a sd or cor row is refused for the same reason. brms narrows such a row to one coefficient of a block; frmtmb resolves those classes per BLOCK, so applying the row without its coef would put the density on every standard deviation of the block, which is a wider prior than the one written. coef on class "b" narrows as it does in brms and is unaffected.

Every refused row of a table is named in ONE message, because a table is edited as a whole and stopping at the first bad row costs a round trip per bad row.

brms's tag and check have no counterpart: tag names a prior for reuse inside a Stan program, and check passes an unchecked string through to one. frmtmb compiles no Stan program, so both are omitted rather than accepted and ignored.

A distributional parameter's own class

A distributional parameter has TWO spellings, and which one applies is decided by the model rather than by taste. They are brms's own two, and brms accepts each only on the model the other does not:

class = "sigma"

a density on sigma ITSELF, on its natural scale. Available when sigma has no predictor of its own, which is the model where sigma is a single number.

class = "Intercept", dpar = "sigma"

a density on the LINK-scale intercept of sigma's linear predictor. Available when the model gives sigma a formula, sigma ~ 1 included.

Writing a formula for a parameter is what replaces the parameter with a linear predictor, so bf(y ~ x, sigma ~ 1) has no sigma to put a density on, and bf(y ~ x) has no Intercept_sigma. Each spelling is refused by name on the other's model, naming the one that applies, because a silently retargeted prior is a different model rather than no model.

class = "b", dpar = "sigma" addresses that predictor's SLOPES and is on the link scale, in both packages. It needs slopes to exist: on sigma ~ 1 the predictor is an intercept only, so the row addresses nothing, and it is refused rather than accepted as a silent no-op. brms refuses it there too.

A distributional class names ONE parameter, so it takes resp and neither coef nor group; both are refused rather than dropped. On a multivariate model it needs resp, as it does in brms: without it, the specification is refused.

get_prior() lists whichever of the two spellings a model offers. Where a parameter has NEITHER, because frmtmb refuses its class by name, the table leaves it out rather than advertising a slot nothing can fill: a mixture proportion with no predictor of its own is one, and ?set_prior's refusal says where that quantity lives.

Examples

set.seed(1)
dd <- data.frame(x = rnorm(100), z = rnorm(100),
                 g = factor(rep(1:10, 10)))
dd$y <- rnorm(100, 1 + 0.5 * dd$x + rnorm(10, 0, 0.8)[dd$g], 1)

# `+` combines specifications; the class-wide one goes first so the
# coefficient-specific one can override it
pr <- set_prior("normal(0, 1)", class = "b") +
  set_prior("normal(0, 0.2)", class = "b", coef = "z") +
  set_prior("exponential(1)", class = "sd", group = "g")
pr
#>           prior class coef group resp dpar nlpar   lb   ub source
#>    normal(0, 1)     b                            <NA> <NA>   user
#>  normal(0, 0.2)     b    z                       <NA> <NA>   user
#>  exponential(1)    sd          g                 <NA> <NA>   user

# the priors penalize the likelihood: the fit is a MAP estimate
fit <- frm(bf(y ~ x + z + (1 | g)) + gaussian(), data = dd, prior = pr)
fixef_by_dpar(fit)$mu
#> (Intercept)           x           z 
#>  1.43923097  0.56382980  0.05323068 
# the tight prior on z shrinks it toward zero
fixef_by_dpar(frm(bf(y ~ x + z + (1 | g)) + gaussian(), data = dd))$mu
#> (Intercept)           x           z 
#>  1.43901107  0.57151174  0.06947068 

# an empty distribution string sets a hard bound only
set_prior("", class = "b", coef = "x", lb = 0)
#> <lower=0> b_x ~ (flat)

# a distributional parameter's own class is a density on the
# parameter itself, on its own scale, where the model gives that
# parameter no predictor. This model does not, so this is the
# spelling it offers, and get_prior() lists it
fit_s <- frm(bf(y ~ x + z) + gaussian(), data = dd,
             prior = set_prior("student_t(3, 0, 2.5)",
                               class = "sigma"))
sigma(fit_s)
#> [1] 1.336249
# with sigma ~ 1 the model has a log-scale intercept instead, and
# that is the slot the prior addresses. brms draws the same line
set_prior("student_t(3, 0, 2.5)", class = "Intercept",
          dpar = "sigma")
#> Intercept_sigma ~ student_t(3, 0, 2.5)

# bounds address a nonlinear parameter the way a distribution does,
# so a guessing rate is held in [0, 1]
set_prior("", nlpar = "guess", lb = 0, ub = 1)
#> <lower=0,upper=1> b_guess ~ (flat)

# the residual-correlation classes are brms's own names
set_prior("normal(0, 0.5)", class = "ar")
#> ar ~ normal(0, 0.5)
set_prior("lkj(2)", class = "rescor")
#> rescor ~ lkj(2)
# and one internal covariance parameter that no class names, such
# as a toep() correlation, by its name as get_prior() lists it
set_prior("", class = "theta", coef = "theta_12", lb = -2, ub = 2)
#> <lower=-2,upper=2> theta_theta_12 ~ (flat)

# class "cor" addresses a correlated block as a whole, brms's
# spelling; eta > 1 pulls the correlation toward zero
dd$z <- rnorm(100)
dd$y2 <- dd$y + rnorm(10, 0, 0.6)[dd$g] * dd$z
fitc <- frm(bf(y2 ~ x + z + (z | g)) + gaussian(), data = dd,
            prior = set_prior("lkj(4)", class = "cor"))
VarCorr(fitc)
#> $g
#> $g$sd
#>            Estimate Est.Error      Q2.5    Q97.5
#> Intercept 0.8478602 0.2064028 0.4433182 1.252402
#> z         0.7600990 0.1980361 0.3719555 1.148243
#> 
#> $g$cor
#> , , Intercept
#> 
#>            Estimate Est.Error       Q2.5     Q97.5
#> Intercept 1.0000000 0.0000000  1.0000000 1.0000000
#> z         0.3342666 0.2368202 -0.1298924 0.7984256
#> 
#> , , z
#> 
#>            Estimate Est.Error       Q2.5     Q97.5
#> Intercept 0.3342666 0.2368202 -0.1298924 0.7984256
#> z         1.0000000 0.0000000  1.0000000 1.0000000
#> 
#> 
#> $g$cov
#> , , Intercept
#> 
#>            Estimate Est.Error        Q2.5     Q97.5
#> Intercept 0.7188669 0.3500014  0.03287685 1.4048570
#> z         0.2154207 0.1706862 -0.11911814 0.5499595
#> 
#> , , z
#> 
#>            Estimate Est.Error        Q2.5     Q97.5
#> Intercept 0.2154207 0.1706862 -0.11911814 0.5499595
#> z         0.5777505 0.3010540 -0.01230454 1.1678056
#> 
#> 
#> 
#> $residual__
#> $residual__$sd
#>   Estimate  Est.Error      Q2.5   Q97.5
#>  0.9763468 0.07648279 0.8264433 1.12625
#> 
#> 

# get_prior() shows which rows a design offers
get_prior(bf(y ~ x + z + (1 | g)) + gaussian(), data = dd)
#> route = "fit": the prior defaults frm() applies
#>    prior     class      coef group resp dpar nlpar lb ub  source
#> 1 (flat) Intercept                                 NA NA default
#> 2 (flat)         b                                 NA NA default
#> 3 (flat)         b         x                       NA NA default
#> 4 (flat)         b         z                       NA NA default
#> 5 (flat)        sd                                 NA NA default
#> 6 (flat)        sd               g                 NA NA default
#> 7 (flat)        sd Intercept     g                 NA NA default
#> 8 (flat)     sigma                                 NA NA default

# prior() quotes its first argument, brms's spelling, and reaches
# the same machinery
prior(normal(0, 1), class = "b")
#> b ~ normal(0, 1)