Public Documentation
Documentation for ModifiedDistributions's public interface.
Contents
Index
ModifiedDistributions.IdentityLinkModifiedDistributions.LogLinkModifiedDistributions.LogitLinkModifiedDistributions.AbstractModifiedDistributionModifiedDistributions.AffineModifiedDistributions.HazardLinkModifiedDistributions.ModifiedModifiedDistributions.TransformedModifiedDistributions.WeightedModifiedDistributions.affineModifiedDistributions.cumulativeModifiedDistributions.get_distModifiedDistributions.get_dist_recursiveModifiedDistributions.hazard_linkModifiedDistributions.modifyModifiedDistributions.series_transformModifiedDistributions.thinModifiedDistributions.weight
Public API
ModifiedDistributions.AbstractModifiedDistribution Type
abstract type AbstractModifiedDistribution{F<:Distributions.VariateForm, S<:Distributions.ValueSupport} <: Distributions.Distribution{F<:Distributions.VariateForm, S<:Distributions.ValueSupport}Supertype of the single-base modifier leaves that wrap one inner distribution and modify it: Affine, Weighted, Transformed, Modified. CensoredDistributions' TimeChange and Shared leaves stay upstream until the migration (CensoredDistributions#343) lands. Parametric on variate form for symmetry with the upstream hierarchy.
Required methods a concrete subtype implements (the leaf interface):
an inner base reachable as
.dist(the defaultshowaccessor; overrideModifiedDistributions._modified_innerif stored elsewhere) and viaget_dist;the univariate interface (
pdf/logpdf/cdf/quantile/minimum/maximum/insupport/params), forwarded or specialised;optionally
Base.show; the default below printsName(inner).
The free_leaf / rewrap_leaf round-trip verbs are owned by ComposedDistributions.jl and live in its package extension, so they are not part of this package's contract.
Verify a subtype with ModifiedDistributions.TestUtils.test_modified_interface.
Fields
sourceModifiedDistributions.Affine Type
struct Affine{D<:(Distributions.UnivariateDistribution), T<:Real, S<:Distributions.ValueSupport} <: ModifiedDistributions.AbstractModifiedDistribution{Distributions.Univariate, S<:Distributions.ValueSupport}The distribution of a deterministic affine transform Y = scale * X + shift of an inner distribution X, with scale > 0 and any real shift.
For a continuous inner distribution, computed by the change-of-variables for a strictly increasing affine map: with x = (y - shift) / scale,
For a discrete inner distribution, the probability mass moves to the rescaled lattice without the Jacobian term: P(Y = y) = P(X = (y - shift) / scale).
Affine is a UnivariateDistribution with the value support of the inner distribution, so it works anywhere a distribution is expected.
See also
affine: constructor function
Fields
dist::Distributions.UnivariateDistribution: The inner distribution being transformed.scale::Real: The positive multiplicative scale.shift::Real: The additive shift.
ModifiedDistributions.HazardLink Type
struct HazardLink{G, GI}A link for the hazard modification carried by a Modified distribution.
The modification acts on the hazard through the link g,
so log gives proportional hazards and identity gives additive hazards. A HazardLink pairs the link g with its inverse invlink (g⁻¹); the three named links (LogLink, IdentityLink, LogitLink) are built-in, and any invertible callable can be wrapped with hazard_link. Only the log and identity links have analytic forms; modify rejects the others until numeric integration is supported.
See also
Fields
g::Any: The linkgmapping a hazard onto the modification scale.invlink::Any: The inverse linkg⁻¹mapping back to a hazard.
ModifiedDistributions.IdentityLink Constant
IdentityLinkThe identity link (additive hazards): g = g⁻¹ = identity.
IdentityLink adds to the cumulative hazard from the support minimum m, modify).
Examples
using ModifiedDistributions, Distributions
# Additive-hazards modification of an Exponential delay.
modify(Exponential(1.0), 0.5; link = ModifiedDistributions.IdentityLink)See also
modify: the verb that consumes a link.HazardLink: the underlying link type.
ModifiedDistributions.LogLink Constant
LogLinkThe log link (proportional hazards): g = log, g⁻¹ = exp.
LogLink scales the survival function, modify.
Examples
using ModifiedDistributions, Distributions
# Proportional-hazards modification of an Exponential delay.
modify(Exponential(1.0), 0.5; link = ModifiedDistributions.LogLink)See also
modify: the verb that consumes a link.HazardLink: the underlying link type.
ModifiedDistributions.LogitLink Constant
LogitLinkThe logit link: g = logit, g⁻¹ = logistic.
LogitLink pairs the logit with its logistic inverse. On a continuous base it requires numeric cumulative-hazard integration, which this package does not yet provide, so modify rejects it with an ArgumentError.
Examples
using ModifiedDistributions
# The logit link pair; modify rejects it until numeric integration lands.
ModifiedDistributions.LogitLinkSee also
modify: the verb that consumes a link.HazardLink: the underlying link type.
ModifiedDistributions.Modified Type
struct Modified{D<:(Distributions.UnivariateDistribution), E<:Real, L<:ModifiedDistributions.HazardLink} <: ModifiedDistributions.AbstractModifiedDistribution{Distributions.Univariate, Distributions.Continuous}A distribution whose hazard is modified through a link.
Modified carries a base distribution dist, a hazard effect and a HazardLink link, and lazily instantiates the modified hazard
in logpdf/cdf/ccdf/rand, where g is the link and h(t) = f(t)/S(t) the base hazard. The modification is never materialised eagerly, so a Modified composes with everything that consumes a UnivariateDistribution.
Two analytic paths are provided, chosen by dispatch on the link:
LogLink: proportional hazards, ;IdentityLinkwith a non-negative effect and a finite lower support boundm: additive hazards, .
Other links (and negative additive effects) need numeric cumulative-hazard integration and are rejected at construction (see modify).
See also
modify: the constructor verb.
Fields
dist::Distributions.UnivariateDistribution: The base distribution whose hazard is modified.effect::Real: The hazard modification effect on the link scale.link::ModifiedDistributions.HazardLink: The hazard linkgand its inverse.
ModifiedDistributions.Transformed Type
struct Transformed{D<:(Distributions.UnivariateDistribution), Op} <: ModifiedDistributions.AbstractModifiedDistribution{Distributions.Univariate, Distributions.ValueSupport}A distribution carrying a forward-transform op, intended for a count series a downstream convolution layer produces. Transparent to logpdf and to every other distribution method (they delegate to the inner distribution). Construct with the generic series_transform or the specialised thin / cumulative.
See also
series_transform,thin,cumulative: constructors
Fields
dist::Distributions.UnivariateDistribution: The inner distribution.op::Any: The forward op applied to a convolved series.
ModifiedDistributions.Weighted Type
struct Weighted{D<:(Distributions.UnivariateDistribution), T<:Union{Missing, Real}} <: ModifiedDistributions.AbstractModifiedDistribution{Distributions.Univariate, Distributions.ValueSupport}A distribution wrapper that applies a weight to the log-probability of an underlying distribution. This is primarily used where observations have associated counts or weights.
Only the logpdf method is affected by the weight - all other methods (pdf, cdf, sampling, etc.) delegate directly to the underlying distribution.
Weight Types Supported
The Weighted struct supports three different weight scenarios:
Real weights: Constructor weight is a specific value (e.g.,
2.5)Missing weights: Constructor weight is
missing, allowing weights to be provided at observation time via joint observations(value = x, weight = w)Zero weights: Handled specially to return
-Infand avoid NaN from0 * -Inf
Examples
using ModifiedDistributions, Distributions
# Single weighted observation
d = LogNormal(1.5, 0.5)
wd = weight(d, 10.0) # Observation with weight/count of 10
# Weighted log-probability calculation
observed_value = 2.0
weighted_logpdf = logpdf(wd, observed_value)
# Compare with manual calculation
manual_logpdf = 10.0 * logpdf(d, observed_value)
# weighted_logpdf ≈ manual_logpdfFields
dist::Distributions.UnivariateDistribution: The underlying distribution being weighted.weight::Union{Missing, Real}: The weight to apply to log-probabilities.
ModifiedDistributions.affine Function
affine(
dist::Distributions.UnivariateDistribution;
scale,
shift
) -> ModifiedDistributions.Affine{D, Float64} where D<:(Distributions.UnivariateDistribution)Create an affine-transformed distribution Y = scale * X + shift.
Arguments
dist: the inner distributionX.
Keyword Arguments
scale: positive multiplicative factor (default1).shift: additive offset (default0).
Examples
using ModifiedDistributions, Distributions
d = affine(LogNormal(1.5, 0.5); scale = 2.0, shift = 1.0)
logpdf(d, 5.0)See also
Affine: the wrapped type
ModifiedDistributions.cumulative Function
cumulative(
dist::Distributions.UnivariateDistribution
) -> ModifiedDistributions.Transformed{D, ModifiedDistributions.CumulativeOp} where D<:(Distributions.UnivariateDistribution)Accumulate a distribution's forward count series.
cumulative(d) is transform with a running-sum op intended for a downstream count series, giving cumulative counts (cumulative incidence, cumulative deaths). Transparent to logpdf.
Arguments
d: the inner distribution.
Examples
using ModifiedDistributions, Distributions
d = cumulative(Gamma(2.0, 1.0))
logpdf(d, 2.0) == logpdf(Gamma(2.0, 1.0), 2.0)See also
series_transform: the generic forward transformthin: a fixed forward factor
ModifiedDistributions.get_dist Function
get_dist(d) -> Distributions.UnivariateDistributionExtract the underlying distribution from a wrapped distribution type.
This protocol provides a consistent interface for extracting the core distribution from the modifier wrappers in this package (and any downstream wrapper that adds a method). For unwrapped distributions, it returns the distribution unchanged.
Arguments
d: A distribution or wrapped distribution.
Returns
The underlying distribution. For base distributions, returns d unchanged.
Examples
using ModifiedDistributions, Distributions
# Base distribution - returns unchanged
d1 = Normal(0, 1)
get_dist(d1)
# Affine-transformed distribution
d2 = affine(LogNormal(1.5, 0.5); scale = 2.0)
get_dist(d2)get_dist(
d::ModifiedDistributions.Affine
) -> Distributions.UnivariateDistributionExtract the underlying distribution from an affine-transformed distribution.
Returns the inner distribution before the affine transform was applied.
sourceget_dist(
d::ModifiedDistributions.Weighted
) -> Distributions.UnivariateDistributionExtract the underlying distribution from a weighted distribution.
Returns the base distribution before weighting was applied.
sourceget_dist(
d::ModifiedDistributions.Transformed
) -> Distributions.UnivariateDistributionExtract the underlying distribution from a forward-transformed distribution.
Returns the inner distribution before the forward-transform op was attached.
sourceget_dist(
d::ModifiedDistributions.Modified
) -> Distributions.UnivariateDistributionExtract the underlying distribution from a hazard-modified distribution.
Returns the base distribution before the hazard modification was applied.
sourceModifiedDistributions.get_dist_recursive Function
get_dist_recursive(d) -> AnyRecursively extract the underlying distribution from nested wrapper types.
This function keeps applying get_dist until it reaches a distribution that doesn't have a specialised method, meaning no further unwrapping is possible.
Arguments
d: A distribution or nested wrapped distribution.
Returns
The deeply underlying distribution after all unwrapping is complete.
Examples
using ModifiedDistributions, Distributions
# Single wrapper - same as get_dist
wd = weight(LogNormal(1.5, 0.75), 2.0)
get_dist_recursive(wd)
# Nested wrappers
nested = weight(affine(Normal(0, 1); scale = 2.0), 3.0)
get_dist_recursive(nested)
# Base distribution - returns unchanged
get_dist_recursive(Normal(0, 1))Note
For a wrapper that unwraps to a vector of components, this function applies recursive extraction to each component, potentially returning mixed types of underlying distributions.
sourceModifiedDistributions.hazard_link Function
hazard_link(g, invlink) -> ModifiedDistributions.HazardLinkWrap a link and its inverse as a HazardLink.
The link g maps a hazard onto the scale the additive effect acts on, and invlink maps back. Use the built-in LogLink or IdentityLink for the analytic choices; this constructor is for a user-supplied invertible callable. Note that modify currently rejects links other than log and identity, since general links need numeric cumulative-hazard integration.
Arguments
g: the link functiong.invlink: the inverse linkg⁻¹.
Examples
using ModifiedDistributions
# A complementary-log-log link.
cloglog = ModifiedDistributions.hazard_link(
h -> log(-log1p(-h)), x -> -expm1(-exp(x)))See also
modify: the verb that consumes a link.
ModifiedDistributions.modify Function
modify(
dist::Distributions.UnivariateDistribution,
effect::Real;
link
) -> ModifiedDistributions.Modified{D, E, ModifiedDistributions.HazardLink{typeof(log), typeof(exp)}} where {D<:(Distributions.UnivariateDistribution), E<:Real}Modify the hazard of a distribution through a link.
modify(d, effect; link = log) returns a Modified distribution whose hazard is g is the link (log for proportional hazards, identity for additive hazards). The modification is instantiated lazily, so the result composes everywhere a UnivariateDistribution does.
Both supported links use closed forms. The identity link requires effect >= 0: a negative additive effect can push the hazard below zero, which needs hazard clamping and numeric cumulative-hazard integration (see CensoredDistributions#670/#680); that path stays upstream in CensoredDistributions, as does the discrete (interval-censored) path. Links other than log and identity are rejected for the same reason. The identity link also requires a base with a finite lower support bound m (the extra hazard accrues from m, so an unbounded-below base has no valid additive form).
Arguments
d: the base continuous distribution.effect: the scalar hazard modification on the link scale.
Keyword Arguments
link: the hazard link. The functionslog(default) andidentity, the symbols:log/:identity, or aHazardLink.
Examples
using ModifiedDistributions, Distributions
# Proportional hazards: halve the hazard of a LogNormal delay.
d = modify(LogNormal(1.5, 0.5), -log(2.0); link = log)
ccdf(d, 2.0)
# Additive hazards: a constant extra hazard.
da = modify(LogNormal(1.5, 0.5), 0.2; link = identity)
cdf(da, 2.0)See also
Modified: the wrapped type.hazard_link: wrap a custom link pair.
modify(
dist::Distributions.UnivariateDistribution,
_::Nothing
) -> Distributions.UnivariateDistributionReturn the distribution unmodified when the effect is nothing.
This lets callers thread an optional hazard effect through modify(dist, effect) and pass nothing to mean "no modification": the distribution is returned unchanged, mirroring weight(dist, nothing).
Examples
using ModifiedDistributions, Distributions
d = LogNormal(1.5, 0.5)
modify(d, nothing) === dModifiedDistributions.series_transform Function
series_transform(
d::Distributions.UnivariateDistribution,
op
) -> ModifiedDistributions.TransformedMap a distribution's convolved count series through a forward op.
series_transform(d, op) carries op (a thin/cumulative op or any callable series -> series) intended for the series a downstream convolution layer produces. Transparent to logpdf. Prefer thin / cumulative for the common cases; use series_transform for an arbitrary deterministic series map. Renamed from transform so it cannot clash with DataFrames.transform (#35).
Arguments
d: the inner distribution.op: a forward op or a callableseries -> series.
Examples
using ModifiedDistributions, Distributions
d = series_transform(Gamma(2.0, 1.0), s -> 0.5 .* s)
logpdf(d, 2.0) == logpdf(Gamma(2.0, 1.0), 2.0)See also
thin,cumulative: specialised forward transforms
ModifiedDistributions.thin Function
thin(
dist::Distributions.UnivariateDistribution,
p::Real
) -> ModifiedDistributions.Transformed{D, Op} where {D<:(Distributions.UnivariateDistribution), Op<:ModifiedDistributions.ThinOp}Thin a distribution's forward count by a probability p.
thin(d, p) is series_transform with a fixed factor p ∈ [0, 1] intended to be multiplied into a downstream count series (e.g. ascertainment of cases, the infection fatality ratio for deaths). Transparent to logpdf. thin(d, nothing) returns d unchanged.
Arguments
d: the inner distribution.p: the thinning probability in.
Examples
using ModifiedDistributions, Distributions
d = thin(LogNormal(1.5, 0.5), 0.3)
logpdf(d, 2.0) == logpdf(LogNormal(1.5, 0.5), 2.0)See also
series_transform: the generic forward transformcumulative: cumulative-sum a series
ModifiedDistributions.weight Function
weight(
dist::Distributions.UnivariateDistribution,
w::Real
) -> ModifiedDistributions.Weighted{D, T} where {D<:(Distributions.UnivariateDistribution), T<:Real}Create a weighted distribution where the log-probability is scaled by w.
A Weighted distribution will contribute w * logpdf(dist, x) to the log-probability when evaluating logpdf(weighted_dist, x). Unlike an ad hoc w * logpdf(dist, x) term in model code, the result is still a real distribution whose sampling delegates to dist, so a Turing.jl model (or any PPL built on Distributions.jl) that uses it stays a complete generative model with working prior and posterior-predictive simulation.
Examples
using ModifiedDistributions, Distributions
# For aggregated count data
y_obs = 3.5 # Observed value
n_count = 25 # Number of times this value was observed
d = Normal(2.0, 1.0)
weighted_d = weight(d, n_count)
# Weighted log-probability calculation
weighted_logpdf = logpdf(weighted_d, y_obs)
# equivalent to: n_count * logpdf(d, y_obs)weight(
dist::Distributions.UnivariateDistribution,
_::Nothing
) -> Distributions.UnivariateDistributionReturn the distribution unweighted when the weight is nothing.
This lets callers thread an optional weight through weight(dist, w) and pass nothing to mean "no weight": the distribution is returned unchanged.
Examples
using ModifiedDistributions, Distributions
d = Normal(2.0, 1.0)
weight(d, nothing) === dweight(
dist::Distributions.UnivariateDistribution,
weights::AbstractVector{<:Real}
) -> AnyCreate a product distribution of weighted distributions, each with a different weight.
A Product distribution of Weighted distributions suitable for vectorised observations.
Arguments
dist: The univariate distribution to be replicated and weighted for each observationweights: Vector of weights to apply to each copy of the distribution
Examples
using ModifiedDistributions, Distributions
y_obs = [3.5, 4.2, 3.8] # Observed values
n_counts = [25, 10, 15] # Counts for each observation
d = Normal(2.0, 1.0)
weighted_dists = weight(d, n_counts)
# Weighted log-probability calculation
weighted_logpdf = logpdf(weighted_dists, y_obs)
# equivalent to: sum(n_counts .* logpdf.(d, y_obs))See also
Weighted: The underlying weighted distribution type
weight(
dists::AbstractVector{<:Distributions.UnivariateDistribution},
weights::AbstractVector{<:Real}
) -> AnyCreate a product distribution of weighted distributions, where each distribution has its own weight.
A Product distribution of Weighted distributions suitable for vectorised observations with different distributions.
Examples
using ModifiedDistributions, Distributions
y_obs = [3.5, 4.2, 3.8] # Observed values
dists = [Normal(2.0, 0.5), Normal(2.5, 0.8), Normal(1.8, 0.6)]
n_counts = [25, 10, 15] # Counts for each observation
weighted_dists = weight(dists, n_counts)weight(
dist::Distributions.UnivariateDistribution
) -> ModifiedDistributions.Weighted{D, Missing} where D<:(Distributions.UnivariateDistribution)Create a weighted distribution with missing constructor weight.
Useful for creating distributions where weights will be provided at observation time. Uses missing as constructor weight, enabling observation weight to be used directly.
Examples
using ModifiedDistributions, Distributions
d = Normal(2.0, 0.5)
# Create weighted distribution with missing constructor weight
weighted_dist = weight(d)
# Weight provided at observation time via joint observations
logpdf(weighted_dist, (value = 3.5, weight = 25))weight(
dists::AbstractVector{<:Distributions.UnivariateDistribution}
) -> AnyCreate a product distribution of weighted distributions with missing constructor weights.
Useful for creating distributions where weights will be provided at observation time. Each distribution uses missing as constructor weight, enabling observation weight to be used directly.
Examples
using ModifiedDistributions, Distributions
y_obs = [3.5, 4.2, 3.8] # Observed values
dists = [Normal(2.0, 0.5), Normal(2.5, 0.8), Normal(1.8, 0.6)]
# Create weighted distributions with missing constructor weights
weighted_dists = weight(dists)
# Weights provided at observation time via joint observations
logpdf(weighted_dists, (values = y_obs, weights = [25, 10, 15]))