Skip to content

Getting started

reparameterise wraps a distribution family so that its moments are its parameters, whichever package the family is defined in.

julia
using ReparameterisedDistributions, Distributions

A first example

A delay can be elicited as a mean and a standard deviation. A prior belongs on that mean, not on a shape parameter that only implies it. reparameterise wraps a native family so that the moments are its parameters.

julia
d = reparameterise(LogNormal; mean = 8.0, sd = 2.0)
reparameterise(LogNormal; mean = 8.0, sd = 2.0)
  native: Distributions.LogNormal{Float64}(μ=2.0491292307716185, σ=0.24622067706923975)

params reports the moments, not the native (mu, sigma). Every other method works exactly as it would on the native distribution.

julia
params(d), mean(d), std(d), logpdf(d, 7.5)
((8.0, 2.0), 7.999999999999998, 1.9999999999999996, -1.5419758370451855)

The wrapper takes its variate form and value support from the family it wraps, so a wrapped discrete family stays discrete.

julia
nb = reparameterise(NegativeBinomial; mean = 10.0, overdispersion = 0.5)

(mean(nb), var(nb))
(10.000000000000002, 60.00000000000001)

Invalid moments

Constraining each moment on its own does not always keep the combination attainable. A Beta needs sd^2 < mean * (1 - mean), so a positive mean and a positive standard deviation can still describe no Beta at all. check_args = false turns the constructor check off, so a proposal like that gives logpdf == -Inf rather than raising mid-gradient.

julia
bad = reparameterise(Beta; mean = 0.2, sd = 0.5, check_args = false)

logpdf(bad, 0.3)
-Inf

Every other method still converts, so an invalid distribution has no mean, no quantile and no draw. Asking for one raises.

Supported parameterisations

FamilyParametersConversion
LogNormalmean, sdthe moments of the distribution, not of its logarithm
LogNormalmean, varas above, given the variance
Gammamean, sdscale = var / mean, shape = mean² / var
Gammamean, varas above, given the variance
Gammamean, shapescale = mean / shape; the shape is native
Gammashape, ratescale = 1 / rate; the shape is native
NegativeBinomialmean, overdispersionvar = mean + overdispersion · mean²
NegativeBinomialmean, dispersionvar = mean + mean² / dispersion, the reciprocal convention
Exponentialratescale = 1 / rate
SkewNormalcentre, scale, mass_below_centrealpha = tan(π · (1/2 − mass_below_centre))
Betamean, sdnu = mean·(1−mean)/var − 1; alpha = mean·nu, beta = (1−mean)·nu
Betamean, varas above, given the variance
InverseGaussianmean, sdlambda = mean³ / var; the mean is native
InverseGaussianmean, varas above, given the variance
Weibullmean, sdnumeric: the CV pins the shape by a scalar root-find; the scale then follows in closed form
Weibullmean, varas above, given the variance

Weibull(mean, sd) has no exact closed form. Its gradient stays exact under automatic differentiation.

A family is registered with two methods, documented in Adding a reparameterisation, with the reference in Public API.

Rescaling a moment

rescale(d, factor) scales one of d's registered moments by factor, holding the others fixed. It routes through whichever parameterisation d was built under.

julia
g = reparameterise(Gamma; mean = 8.0, shape = 2.0)

(mean(g), mean(rescale(g, 2.0)))
(8.0, 16.0)

The shape stays at 2.0 and only the mean moves. A discrete family scales in moment coordinates rather than by an affine transform of the native support.

julia
mean(rescale(nb, 3.0))
30.0

parameter defaults to :mean and can name any of d's registered parameters. Naming one that is not registered for d's family raises a DomainError rather than applying the factor under different semantics.

Learning more

The layout, navigation, and infrastructure of this site are generated by EpiAwarePackageTools. Its docs cover customising the generated pages and how template sync keeps this repository current.