Skip to contents

Returns a brms custom family for the discrete normal distribution with location fixed at 0, obtained from the continuous Normal(0, sigma) by CDF differencing: P(Z = z) = F(z + 0.5) - F(z - 0.5). The single parameter is sigma (log link), the SD of the continuous distribution before discretisation; the mean is zero. The PMF and CCDF are closed-form: the Stan code computes the PMF with normal_lcdf for z < 0 and with erfc() for z >= 0, and the CCDF with erfc() (see "Evaluation in the upper tail"). As in dlaplace1(), they require no Bessel function and no iteration cap.

Use in a brm() call as: brm(y ~ ..., family = dnorm1(), stanvars = dnorm1_stanvars(), data = ...)

Usage

dnorm1()

dnorm1_stanvars()

log_lik_dnorm1(i, prep)

posterior_predict_dnorm1(i, prep, ...)

posterior_epred_dnorm1(prep)

Value

dnorm1() returns a brms custom_family object. dnorm1_stanvars() returns a stanvars object holding the Stan code for dnorm1_lpmf. log_lik_dnorm1() returns a numeric vector of log-densities, one per posterior draw, for observation i. posterior_predict_dnorm1() returns a vector of simulated differences, one per posterior draw, for observation i, drawn within the truncation bounds of that observation if it has any. posterior_epred_dnorm1() returns a draws x observations matrix of means, taken over the truncated distribution on any row that is bounded.

Parameter named mu

As in skellam1() and dlaplace1(), brms::custom_family() requires a parameter named "mu", and in dnorm1() that parameter is sigma, the SD, not a mean. See skellam1() for the consequences for formulas and priors.

Scale parameter

sigma is the SD of the continuous normal distribution and enters the normal CDF unchanged. dlaplace1(), by contrast, converts sigma to the Laplace scale b first. The SD of the discretised distribution is close to sqrt(sigma^2 + 1/12) for sigma >= 0.5: larger than sigma by 4.1% at sigma = 1 and by 1.0% at sigma = 2.

Evaluation in the upper tail

The Stan function normal_lccdf returns negative infinity for standardised arguments above about 8.25 (stan-dev/math#1985). dnorm1_lccdf therefore computes the upper-tail probability as 0.5 * erfc(x / (sigma * sqrt(2))), and dnorm1_lpmf uses the same form for z >= 0. In R, log_lik_dnorm1() uses pnorm(lower.tail = FALSE) for z >= 0, because log(pnorm(z + 0.5) - pnorm(z - 0.5)) evaluates to log(0) once z exceeds about 8.5 SDs. Both the Stan and the R log-PMF are accurate until they underflow below about -708, near 38 SDs from 0.

See also

dnorm1_lccdf_stanvars() for truncation; dnorm2() for the free-mean version; skellam1() and dlaplace1() for the same fixed mean under a Skellam and a heavier-tailed alternative.