| Title: | Bayesian Dynamic Models for Count Time Series |
|---|---|
| Description: | Fits Bayesian state-space models for count time series using a latent log-rate (Poisson), latent logit (binomial) or latent additive-log-ratio (multinomial choice counts) formulation. Each latent trajectory follows a first-order random walk or a stationary AR(1) process and is sampled by Metropolis-within-Gibbs using the implied Gaussian Markov random field full conditionals. The latent increments can be Gaussian, Student-t, a finite scale mixture of normals, or follow a stochastic volatility process, and the Poisson and binomial families support zero inflation. It implements and extends the methodology of Zens and Bijak (2026) <doi:10.1214/26-AOAS2171>. |
| Authors: | Gregor Zens [aut, cre] |
| Maintainer: | Gregor Zens <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-09-28 15:54:50 UTC |
| Source: | https://github.com/cran/DynCount |
Builds the prior hyperparameters used by fit_dynamic_model(). Called with
no arguments it returns weakly informative defaults.
dynamic_prior( var_shape = 0.01, var_rate = 0.01, df_min = 3, df_mean_excess = 6, mix_components = 2, mix_concentration = 1, mix_var_shape = 2.5, mix_var_rate = 0.5, sv_prior = NULL, zi_open_a = 1, zi_open_b = 1, ar_rho_mean = 0, ar_rho_sd = 1, mu_mean = 0, mu_sd = 1, init_mean = 0, init_var = 100 )dynamic_prior( var_shape = 0.01, var_rate = 0.01, df_min = 3, df_mean_excess = 6, mix_components = 2, mix_concentration = 1, mix_var_shape = 2.5, mix_var_rate = 0.5, sv_prior = NULL, zi_open_a = 1, zi_open_b = 1, ar_rho_mean = 0, ar_rho_sd = 1, mu_mean = 0, mu_sd = 1, init_mean = 0, init_var = 100 )
var_shape |
Shape of the inverse-gamma prior on the innovation
variance/scale. Default |
var_rate |
Rate of the inverse-gamma prior on the innovation
variance/scale. Default |
df_min |
Lower bound for the Student-t degrees of freedom. Default |
df_mean_excess |
Prior mean of |
mix_components |
Number of components in the scale-mixture innovation
structure. Default |
mix_concentration |
Symmetric Dirichlet concentration for the mixture
weights. Default |
mix_var_shape, mix_var_rate
|
Shape and rate of the inverse-gamma prior
on the relative variance of each mixture component (used only when
|
sv_prior |
Optional stochvol prior specification for the
stochastic-volatility innovation structure. Default |
zi_open_a, zi_open_b
|
Beta prior parameters for the gate-open
probability in zero-inflated models. Default |
ar_rho_mean, ar_rho_sd
|
Mean and standard deviation of the Gaussian
prior on the AR(1) coefficient |
mu_mean, mu_sd
|
Mean and standard deviation of the Gaussian prior on the
drift/intercept |
init_mean, init_var
|
Mean and variance of the Gaussian prior on
the initial latent state, used under both random-walk and AR(1) dynamics.
Defaults |
The model places a GMRF latent process on the series (a log-rate
for the Poisson family, a logit for the binomial family, and one
additive-log-ratio series per non-baseline category for the multinomial
family): either a first-order
random walk (latent_dynamics = "rw") or an AR(1) process
(latent_dynamics = "ar1"). The increments
(with for the
random walk and unless a drift/intercept is included) are given
one of four innovation distributions, each governed by some of the priors
below.
Innovation variance (all structures). The baseline increment
variance (or, for the "t"/"mixture" structures, the
overall scale) has an inverse-gamma prior
The default is weakly informative for
typical increment standard deviations, but it is not scale-free. For very
smooth or short series, with increment standard deviations of a few
hundredths, the results can be sensitive to this prior. In that regime, check the
sensitivity of the results to a smaller var_rate (which lets
become smaller) and expect slower mixing, because a nearly constant latent
path and a small are strongly dependent a posteriori.
In the multinomial family the same prior is applied independently to every
non-baseline category.
Mixture component variances (innovations = "mixture"). The
relative variances of the mixture components multiply the overall scale
and are given their own prior (default ).
They are kept moderately informative on purpose, as with a vague prior an
empty component would be drawn from an extremely heavy-tailed
distribution and the split between the overall scale and the component
variances is only weakly identified.
Student-t degrees of freedom (innovations = "t"). The degrees of
freedom are modelled as , where
. Thus
and its prior mean is
. Large approaches
the Gaussian case.
Scale mixture (innovations = "mixture"). The mixture uses
mix_components variance components, each with an
prior (see above), and symmetric Dirichlet weights with concentration
mix_concentration.
Stochastic volatility (innovations = "sv"). The log-variance
of the increments follows
, and its
priors are delegated to stochvol. Pass a prior specification
created with stochvol::specify_priors() via sv_prior, or leave it NULL
to use the stochvol defaults.
Zero inflation (zeros = "inflated"). The probability that the
observation "gate" is open (i.e. that a zero is an ordinary sampling zero
rather than a structural zero) has a
prior. The
default Beta(1, 1) is uniform.
AR(1) coefficient (latent_dynamics = "ar1"). When the latent
state follows , the
coefficient is given a Gaussian prior
,
truncated to the stationary region . AR(1) always
carries an intercept
(include_mu = TRUE). Under latent_dynamics = "rw" the coefficient is
fixed at and this prior is unused.
Drift / intercept (include_mu = TRUE). A scalar in the
state equation : a
drift under the random walk () and an intercept
under AR(1) (where it is always enabled). It is given a Gaussian prior
. With
include_mu = FALSE (random walk only), and is not sampled.
Initial state. A proper, fixed
prior (default
) anchors the otherwise-improper GMRF on the first latent
state, under both "rw" and "ar1" dynamics. With the diffuse default
the initial state is
effectively determined by the data.
An object of class "dynamic_prior": a named list of hyperparameters.
# Defaults dynamic_prior() # An informative variance prior and heavier-tailed t innovations dynamic_prior(var_shape = 2.5, var_rate = 0.5, df_min = 2, df_mean_excess = 3)# Defaults dynamic_prior() # An informative variance prior and heavier-tailed t innovations dynamic_prior(var_shape = 2.5, var_rate = 0.5, df_min = 2, df_mean_excess = 3)
Fits a GMRF state-space model in which a latent trajectory evolves
as either a first-order random walk (latent_dynamics = "rw", the default)
or a stationary AR(1) process (latent_dynamics = "ar1"), and the
observations are linked to it through a Poisson (log link), binomial
(logit link) or multinomial (additive-log-ratio link) observation model.
See DynCount-package for an overview.
fit_dynamic_model( y, family = c("poisson", "binomial", "multinomial"), trials = NULL, innovations = c("gaussian", "t", "mixture", "sv"), latent_dynamics = c("rw", "ar1"), include_mu = FALSE, zeros = c("none", "inflated", "missing"), zero_inflation = FALSE, prior = dynamic_prior(), nsave = 4000, nburn = 1000, thin = 1, horizon = 0L, forecast_trials = NULL, forecast_offset = NULL, offset = NULL, baseline = "largest", verbose = FALSE, seed = NULL )fit_dynamic_model( y, family = c("poisson", "binomial", "multinomial"), trials = NULL, innovations = c("gaussian", "t", "mixture", "sv"), latent_dynamics = c("rw", "ar1"), include_mu = FALSE, zeros = c("none", "inflated", "missing"), zero_inflation = FALSE, prior = dynamic_prior(), nsave = 4000, nburn = 1000, thin = 1, horizon = 0L, forecast_trials = NULL, forecast_offset = NULL, offset = NULL, baseline = "largest", verbose = FALSE, seed = NULL )
y |
For the Poisson and binomial families a numeric vector of
non-negative integer observations (counts, or numbers of successes). For
the multinomial family an |
family |
Observation model, |
trials |
For |
innovations |
Distribution of the latent increments, one of
|
latent_dynamics |
Latent state evolution: |
include_mu |
Logical; include a scalar |
zeros |
Zero handling for the Poisson and binomial families: |
zero_inflation |
A single |
prior |
A |
nsave |
Number of posterior draws to keep. Default |
nburn |
Number of burn-in iterations. Default |
thin |
Thinning interval: one draw is kept every |
horizon |
Forecast horizon |
forecast_trials |
For the binomial and multinomial families, the number
of trials (binomial) or the total count per period (multinomial) over the
forecast horizon (length 1, recycled, or length |
forecast_offset |
Known offset over the forecast horizon. For the
Poisson and binomial families a vector of length 1 (recycled) or
|
offset |
Optional known per-observation offset on the linear-predictor
scale. For the Poisson family (length 1 or |
baseline |
Multinomial family only: the baseline category, given as a
column index or a column name of |
verbose |
Logical; print a progress bar. Default |
seed |
Optional random seed for reproducibility. The previous state of the global random number generator is restored after fitting. |
Estimation. The model is estimated by Metropolis-within-Gibbs
MCMC. The latent states are updated one site at a time by adaptive
random-walk Metropolis steps that use their Gaussian Markov random field
(GMRF) full conditionals. States without an observation (the initial
state, structural zeros, zero-total rows) are drawn exactly from their
Gaussian full conditionals. The
innovation parameters, the drift/intercept and the AR(1)
coefficient are updated by Gibbs steps (with a Metropolis step
for the Student-t degrees of freedom).
Multinomial family. With family = "multinomial", y is an
matrix of category counts (rows = time, columns =
categories, ); the row totals are treated as known
trials. One category is the baseline, and the remaining
categories each get their own latent additive-log-ratio (ALR)
series , so that
with known offsets (zero by default). The chosen latent
dynamics, innovation structure and drift/intercept setting apply to every
ALR series, but no parameters are shared across categories. Each
series has its own innovation variance (and, where relevant, degrees of
freedom, mixture components or volatility path), its own and
, and its own copy of prior. The series are coupled only
through the multinomial likelihood, and each series is updated with the
other categories held at their current values. A row with
carries no information about the shares and is handled like
a missing observation. Zero inflation is not available for this family
(zeros must be "none"). Running time grows linearly in .
Zero handling. Under zeros = "inflated" a latent gate decides,
for each observed zero, whether it is structural (gate closed) or an
ordinary sampling zero produced by the Poisson/binomial process (gate
open); the gate-open probability is a single parameter that is constant
over time. See structural_zero_prob(). Under zeros = "missing" the
observed zeros are treated as missing values.
Forecasting. Forecasts are obtained by forward simulation from the
posterior draws, so they can be computed after fitting for any horizon with
forecast.dynamic_fit(). Setting horizon = H additionally simulates an
H-step forecast right after sampling and stores it in the fit (under the
same seed).
Reproducibility. With a seed, the sampler and the fit-time
forecast run with that seed, and the previous state of the global random
number generator is restored afterwards.
An object of class "dynamic_fit": a list with three elements.
drawsPosterior draws only. For the Poisson and binomial families a list of matrices/vectors with one row (or element) per stored draw:
zLatent states aligned with the observations
(draws x n).
z0The initial latent state, one period before the first
observation, which carries the init_mean / init_var prior.
sig2Variance of the increment leading into each
(draws x n); the first column is the increment from
z0.
fitted, yrep
Unconditional fitted means and
posterior predictive replicates; under zeros = "inflated" they
include the zero-inflation gate.
fitted_open, yrep_open
Their conditional-on-gate-open counterparts: the latent-implied mean, and a replicate drawn straight from the observation model.
gate, pi_open
Zero-inflation gate indicators and
gate-open probability; NULL unless zeros = "inflated".
rho, mu
AR(1) coefficient (1 under the random walk)
and drift/intercept (0 unless include_mu = TRUE).
innov_varA representative innovation variance whose
definition depends on innovations: the estimated constant
increment variance for "gaussian"; the marginal
increment variance for "t" () and
"mixture" (); and the
average of the per-increment variances over the
in-sample transitions for "sv". For "t", if a draw has
(possible only when df_min <= 2), the undefined
variance factor is replaced by the convention 3.
scaleThe overall innovation scale
(NULL for "sv").
nuStudent-t degrees of freedom (NULL unless
innovations = "t").
mix_weight, mix_var
Mixture weights and component
variances (), draws x mix_components
(NULL unless innovations = "mixture"). The components are
exchangeable and not identified individually. Within each draw
they are stored in order of increasing variance, which is a
labelling convention rather than an identification, so
per-component summaries are meaningful only if the components
are clearly separated. Label-invariant quantities, such as
innov_var and the forecasts, are unaffected.
sv_mu, sv_phi, sv_sigma
Level, persistence and
volatility of the AR(1) log-variance process (NULL unless
innovations = "sv").
forecast_z, forecast_y
Latent and response forecasts
when horizon >= 1 (NULL otherwise); forecast_y is
unconditional, i.e. includes the gate.
Use yrep, not yrep_open, for posterior predictive checks; without
zero inflation the conditional and unconditional pairs are identical.
See predict.dynamic_fit().
For the multinomial family the same components carry an extra
trailing category dimension, named by the category labels:
latent quantities (z, sig2, forecast_z, mix_weight,
mix_var) are arrays with one slice per non-baseline category, and
z0, rho, mu, innov_var, scale, nu and the sv_*
parameters are draws x (K - 1) matrices; response-scale quantities
(fitted – the expected counts –, yrep,
forecast_y, and the additional fitted_prob / forecast_prob
holding the category shares) are draws x time x K arrays including
the baseline, in the original column order. fitted_open,
yrep_open, gate and pi_open are NULL.
dataThe observed inputs: y, trials (the row totals for the
multinomial family), the series length n, and the resolved
per-observation offset. For the multinomial family also K, the
categories (column labels), and the baseline index and
baseline_name.
specThe model and MCMC specification: family, innovations,
latent_dynamics, include_mu, zeros, prior, nsave, nburn,
thin, horizon, and the forecast-period inputs forecast_offset /
forecast_trials used for the stored forecast (NULL when not
applicable).
dynamic_prior(), forecast.dynamic_fit(), predict.dynamic_fit(),
plot_fitted(), structural_zero_prob(), simulate_dynamic_multinomial()
sim <- simulate_dynamic_poisson(n = 60, sigma = 0.2, log_rate0 = 2, seed = 1) fit <- fit_dynamic_model(sim$y, family = "poisson", nsave = 300, nburn = 200, seed = 1) summary(fit) forecast(fit, horizon = 5) # multinomial choice counts: three categories, baseline chosen automatically simm <- simulate_dynamic_multinomial(n = 40, sigma = 0.15, trials = 100, alr0 = c(-1, -0.5), seed = 2) fitm <- fit_dynamic_model(simm$y, family = "multinomial", nsave = 200, nburn = 100, seed = 2) fitm summary(fitm)$paramssim <- simulate_dynamic_poisson(n = 60, sigma = 0.2, log_rate0 = 2, seed = 1) fit <- fit_dynamic_model(sim$y, family = "poisson", nsave = 300, nburn = 200, seed = 1) summary(fit) forecast(fit, horizon = 5) # multinomial choice counts: three categories, baseline chosen automatically simm <- simulate_dynamic_multinomial(n = 40, sigma = 0.15, trials = 100, alr0 = c(-1, -0.5), seed = 2) fitm <- fit_dynamic_model(simm$y, family = "multinomial", nsave = 200, nburn = 100, seed = 2) fitm summary(fitm)$params
Returns posterior predictive forecasts for the H periods after the end of
the series. The forecasts are obtained by forward simulation from the
stored posterior draws, so any horizon can be requested after fitting. If
the model was fitted with horizon >= 1, the forecast draws stored in the
fit are returned unless horizon, forecast_offset or forecast_trials
is supplied.
## S3 method for class 'dynamic_fit' forecast( object, horizon = NULL, forecast_offset = NULL, forecast_trials = NULL, probs = c(0.025, 0.5, 0.975), seed = NULL, ... )## S3 method for class 'dynamic_fit' forecast( object, horizon = NULL, forecast_offset = NULL, forecast_trials = NULL, probs = c(0.025, 0.5, 0.975), seed = NULL, ... )
object |
A |
horizon |
Forecast horizon |
forecast_offset |
Known offset over the forecast horizon, in the same
format as in |
forecast_trials |
Binomial and multinomial families: the number of
trials (binomial) or the total count per period (multinomial) over the
forecast horizon, of length 1 (recycled) or |
probs |
Quantile probabilities for the summary. Default
|
seed |
Optional random seed for the forward simulation. The previous state of the global random number generator is restored afterwards. |
... |
Unused. |
For every stored posterior draw, the latent path is propagated from the
last in-sample state with
, drawing the
increments from the fitted innovation structure (Gaussian with the drawn
variance, Student-t with the drawn scale and degrees of freedom, the drawn
scale mixture, or the stochastic-volatility process continued from its last
in-sample log-variance). A response is then drawn from the observation
model at each simulated state. The intervals therefore reflect parameter,
state and innovation uncertainty.
Zero inflation. For fits with zeros = "inflated" the response
forecast is unconditional: each draw includes the zero-inflation
gate, so structural zeros are reproduced and the draws are directly
comparable to future observations (like the in-sample yrep, unlike
yrep_open). The latent forecast summary in $latent is gate-free by
construction.
Multinomial family. Response forecasts are multinomial draws with
the totals given by forecast_trials. The summaries are in long format
with a category column. summary and final cover all K categories on
the count scale, prob gives the forecast category shares, and latent
the K - 1 ALR series. draws is a draws x H x K array and
final_draws a draws x K matrix.
An object of class "dynamic_forecast": a list with summary (one
row per horizon , on the response scale), latent
(summary of the forecast latent path), draws (the predictive draws,
draws x H), latent_draws (the latent forecast draws), final (the
single-row summary of the final H-step-ahead forecast), final_draws
(the predictive draws at horizon H), the forecast horizon, and the
forecast_offset / forecast_trials that were used. For the
multinomial family additionally prob (share summary) and prob_draws
(draws x H x K share draws); see Details for the layout.
fit_dynamic_model(), plot_forecast()
sim <- simulate_dynamic_poisson(60, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 300, nburn = 200, seed = 1) fc <- forecast(fit, horizon = 8) fc$summary fc$finalsim <- simulate_dynamic_poisson(60, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 300, nburn = 200, seed = 1) fc <- forecast(fit, horizon = 8) fc$summary fc$final
A longer weekly count series of irregular sea crossings on the Mediterranean route, covering the ISO weeks 2015-W40 to 2025-W11 (494 weeks). The counts are larger in magnitude with fewer zeros than uk_weekly. The series is used in the irregular-migration application of Zens and Bijak (2026).
med_weeklymed_weekly
A data frame with 494 rows and 3 variables:
ISO week label, e.g. "2015-W40".
Non-negative integer count of weekly crossings.
The Monday of the ISO week, as a Date.
Weekly aggregates of detected irregular Mediterranean crossings, compiled from operational/agency records as described in Zens and Bijak (2026), doi:10.1214/26-AOAS2171.
Zens, G. and Bijak, J. (2026). Dynamic Count Models with Flexible Innovation Processes for Irregular Maritime Migration. The Annals of Applied Statistics, 20(2), 1671–1690. doi:10.1214/26-AOAS2171.
summary(med_weekly$count) plot(med_weekly$date, med_weekly$count, type = "h", xlab = "week", ylab = "crossings")summary(med_weekly$count) plot(med_weekly$date, med_weekly$count, type = "h", xlab = "week", ylab = "crossings")
Observed series with the posterior median fitted mean and a credible band on
the response scale. For the multinomial family, one panel per category
showing the observed and expected counts .
plot_fitted(object, level = 0.95, category = NULL, ...)plot_fitted(object, level = 0.95, category = NULL, ...)
object |
A |
level |
Credible level. Default |
category |
Multinomial family only: which categories to draw (names
or indices among the non-baseline categories for |
... |
Passed to |
Invisibly, the fitted summary.
sim <- simulate_dynamic_poisson(60, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 300, nburn = 200, seed = 1) plot_fitted(fit)sim <- simulate_dynamic_poisson(60, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 300, nburn = 200, seed = 1) plot_fitted(fit)
Shows the observed series together with the in-sample fitted mean (median and
credible band) and the forecast (median and credible band) over the forecast
horizon. The forecast is the one stored in the fit, or a new one computed
with forecast.dynamic_fit() when horizon (or another forecast input) is
supplied. For the multinomial family, one panel per category.
plot_forecast( object, level = 0.95, category = NULL, horizon = NULL, forecast_offset = NULL, forecast_trials = NULL, seed = NULL, ... )plot_forecast( object, level = 0.95, category = NULL, horizon = NULL, forecast_offset = NULL, forecast_trials = NULL, seed = NULL, ... )
object |
A |
level |
Credible level. Default |
category |
Multinomial family only: which categories to draw (names
or indices among the non-baseline categories for |
horizon, forecast_offset, forecast_trials, seed
|
Passed to
|
... |
Passed to |
Invisibly, the "dynamic_forecast" object.
sim <- simulate_dynamic_poisson(60, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 300, nburn = 200, seed = 1) plot_forecast(fit, horizon = 12)sim <- simulate_dynamic_poisson(60, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 300, nburn = 200, seed = 1) plot_forecast(fit, horizon = 12)
Shows the posterior median of the latent state (log-rate for the Poisson family, logit for the binomial family, one additive-log-ratio series per non-baseline category for the multinomial family) with a credible band.
plot_latent(object, level = 0.95, category = NULL, ...)plot_latent(object, level = 0.95, category = NULL, ...)
object |
A |
level |
Credible level for the band. Default |
category |
Multinomial family only: which categories to draw (names
or indices among the non-baseline categories for |
... |
Passed to |
Invisibly, the summary data frame used for plotting (in long format
with a category column for the multinomial family).
sim <- simulate_dynamic_poisson(60, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 300, nburn = 200, seed = 1) plot_latent(fit)sim <- simulate_dynamic_poisson(60, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 300, nburn = 200, seed = 1) plot_latent(fit)
Bar chart of the posterior probability that each observed zero is a
structural zero (see structural_zero_prob()), one bar per observed zero
labelled by its time index, with a dotted reference line at 0.5. Requires
a model fitted with zeros = "inflated" (Poisson or binomial family).
plot_zero_inflation(object, ...)plot_zero_inflation(object, ...)
object |
A |
... |
Passed to |
Invisibly, the structural_zero_prob() data frame.
sim <- simulate_dynamic_poisson(80, 0.2, 2, zero_inflation = 0.3, seed = 1) fit <- fit_dynamic_model(sim$y, zero_inflation = TRUE, nsave = 300, nburn = 200, seed = 1) plot_zero_inflation(fit)sim <- simulate_dynamic_poisson(80, 0.2, 2, zero_inflation = 0.3, seed = 1) fit <- fit_dynamic_model(sim$y, zero_inflation = TRUE, nsave = 300, nburn = 200, seed = 1) plot_zero_inflation(fit)
A convenience wrapper that dispatches to the dedicated plotting functions.
## S3 method for class 'dynamic_fit' plot(x, which = c("fitted", "latent", "forecast", "zeros"), ...)## S3 method for class 'dynamic_fit' plot(x, which = c("fitted", "latent", "forecast", "zeros"), ...)
x |
A |
which |
One of |
... |
Passed to the underlying plotting function (e.g. |
Invisibly, the result of the underlying plotting function.
In-sample fitted values and posterior predictive replicates
## S3 method for class 'dynamic_fit' predict( object, type = c("mean", "response", "prob"), conditional = FALSE, probs = c(0.025, 0.5, 0.975), ... )## S3 method for class 'dynamic_fit' predict( object, type = c("mean", "response", "prob"), conditional = FALSE, probs = c(0.025, 0.5, 0.975), ... )
object |
A |
type |
|
conditional |
Logical. Leave |
probs |
Quantile probabilities for the summary. Default
|
... |
Unused. |
A list with summary (a data frame, one row per observation) and
draws (the underlying draws matrix, draws x time). For the multinomial
family summary is in long format with one row per observation and
category (columns time, category, observed, ...) and draws is a
draws x time x K array.
sim <- simulate_dynamic_poisson(40, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 200, nburn = 100, seed = 1) head(predict(fit)$summary) # posterior of the mean of y head(predict(fit, type = "response")$summary) # posterior predictivesim <- simulate_dynamic_poisson(40, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 200, nburn = 100, seed = 1) head(predict(fit)$summary) # posterior of the mean of y head(predict(fit, type = "response")$summary) # posterior predictive
Generates a latent logit process (random walk or AR(1)) and binomial counts, optionally with structural (zero-inflation) zeros.
simulate_dynamic_binomial( n, sigma, trials, logit0 = 0, zero_inflation = 0, rho = 1, mu = 0, offset = 0, seed = NULL )simulate_dynamic_binomial( n, sigma, trials, logit0 = 0, zero_inflation = 0, rho = 1, mu = 0, offset = 0, seed = NULL )
n |
Number of observations. |
sigma |
Standard deviation of the latent increments (Gaussian). |
trials |
Number of trials: a single number (recycled) or a length- |
logit0 |
Initial logit |
zero_inflation |
Structural-zero probability. With probability
|
rho |
AR(1) coefficient of the latent process
|
mu |
Drift (random walk) / intercept (AR(1)) of the latent process.
Default |
offset |
Known offset on the logit scale (length 1 or |
seed |
Optional random seed. The previous state of the global random number generator is restored afterwards. |
A list with components y (successes), trials, logit (latent
path ), prob (plogis(offset + logit)), offset, and
structural (logical, TRUE for structural zeros).
sim <- simulate_dynamic_binomial(n = 50, sigma = 0.15, trials = 40, seed = 1) head(sim$y) # with structural zeros: zi <- simulate_dynamic_binomial(50, 0.15, trials = 40, zero_inflation = 0.2, seed = 1) mean(zi$structural)sim <- simulate_dynamic_binomial(n = 50, sigma = 0.15, trials = 40, seed = 1) head(sim$y) # with structural zeros: zi <- simulate_dynamic_binomial(50, 0.15, trials = 40, zero_inflation = 0.2, seed = 1) mean(zi$structural)
Generates independent latent additive-log-ratio (ALR) processes
(random walk or AR(1)), one per non-baseline category, and multinomial
choice counts with known totals. The ALR series
share no parameters: sigma,
rho and mu may each be a single value (recycled) or a vector of length
giving one value per non-baseline category.
simulate_dynamic_multinomial( n, sigma, trials, alr0 = c(0, 0), baseline = length(alr0) + 1L, rho = 1, mu = 0, offset = 0, categories = NULL, seed = NULL )simulate_dynamic_multinomial( n, sigma, trials, alr0 = c(0, 0), baseline = length(alr0) + 1L, rho = 1, mu = 0, offset = 0, categories = NULL, seed = NULL )
n |
Number of observations. |
sigma |
Standard deviation(s) of the latent increments (Gaussian);
length 1 or |
trials |
Total count per period: a single number (recycled) or a
length- |
alr0 |
Numeric vector of length |
baseline |
The baseline category: a column index in |
rho |
AR(1) coefficient(s) of the latent processes
|
mu |
Drift (random walk) / intercept (AR(1)) of the latent processes;
length 1 or |
offset |
Known offset on the ALR scale: a scalar, a length
|
categories |
Optional character vector of length |
seed |
Optional random seed. The previous state of the global random number generator is restored afterwards. |
A list with components y (an n x K matrix of counts with the
baseline in column baseline), trials, alr (the n x (K - 1) latent
ALR paths ), prob (the n x K matrix of category
probabilities), offset, baseline (the column index) and categories.
sim <- simulate_dynamic_multinomial(n = 50, sigma = 0.15, trials = 200, alr0 = c(-0.5, 0.5), seed = 1) head(sim$y) colSums(sim$y) # fit on the simulated ALR scale by passing the simulated baseline fit <- fit_dynamic_model(sim$y, family = "multinomial", baseline = sim$baseline, nsave = 200, nburn = 100, seed = 1) summary(fit)$paramssim <- simulate_dynamic_multinomial(n = 50, sigma = 0.15, trials = 200, alr0 = c(-0.5, 0.5), seed = 1) head(sim$y) colSums(sim$y) # fit on the simulated ALR scale by passing the simulated baseline fit <- fit_dynamic_model(sim$y, family = "multinomial", baseline = sim$baseline, nsave = 200, nburn = 100, seed = 1) summary(fit)$params
Generates a latent log-rate process (random walk or AR(1)) and Poisson counts, optionally with zero inflation.
simulate_dynamic_poisson( n, sigma, log_rate0 = 1, zero_inflation = 0, rho = 1, mu = 0, offset = 0, seed = NULL )simulate_dynamic_poisson( n, sigma, log_rate0 = 1, zero_inflation = 0, rho = 1, mu = 0, offset = 0, seed = NULL )
n |
Number of observations. |
sigma |
Standard deviation of the latent increments (Gaussian). |
log_rate0 |
Initial log-rate |
zero_inflation |
Probability that the gate is closed (i.e. the
probability of a structural zero) at each time point. |
rho |
AR(1) coefficient of the latent process
|
mu |
Drift (random walk) / intercept (AR(1)) of the latent process.
Default |
offset |
Known log-exposure offset (length 1 or |
seed |
Optional random seed. The previous state of the global random number generator is restored afterwards. |
A list with components y (observed counts), log_rate (the latent
log-rate path ), rate (the mean exp(offset + log_rate)),
offset, and structural (logical, TRUE where a structural zero was
forced).
sim <- simulate_dynamic_poisson(n = 50, sigma = 0.2, log_rate0 = 2, zero_inflation = 0.2, seed = 1) table(sim$y == 0, sim$structural)sim <- simulate_dynamic_poisson(n = 50, sigma = 0.2, log_rate0 = 2, zero_inflation = 0.2, seed = 1) table(sim$y == 0, sim$structural)
For a zero-inflated fit (Poisson or binomial), returns for every observed zero the posterior probability that it is a structural zero (gate closed) rather than an ordinary sampling zero generated by the observation process. A single gate-open probability governs all observations (it does not vary over time or with covariates), while the gate itself is drawn separately for every observation.
structural_zero_prob(object, zeros_only = TRUE)structural_zero_prob(object, zeros_only = TRUE)
object |
A |
zeros_only |
If |
The model introduces a latent gate indicator : when
the gate is open () the count comes from the observation model
(Poisson or binomial); when closed () the count is a structural
zero. The sampler stores for each draw, so the structural-zero
probability is
the posterior mean of the gate being closed. Non-zero observations are
always sampling observations and have structural probability 0.
A data frame with columns time, observed, p_structural
(posterior probability the zero is structural) and p_sampling
(1 - p_structural).
sim <- simulate_dynamic_poisson(60, 0.2, 2, zero_inflation = 0.25, seed = 1) fit <- fit_dynamic_model(sim$y, zero_inflation = TRUE, nsave = 300, nburn = 200, seed = 1) structural_zero_prob(fit)sim <- simulate_dynamic_poisson(60, 0.2, 2, zero_inflation = 0.25, seed = 1) fit <- fit_dynamic_model(sim$y, zero_inflation = TRUE, nsave = 300, nburn = 200, seed = 1) structural_zero_prob(fit)
Summarise a fitted dynamic model
## S3 method for class 'dynamic_fit' summary(object, probs = c(0.025, 0.5, 0.975), ...)## S3 method for class 'dynamic_fit' summary(object, probs = c(0.025, 0.5, 0.975), ...)
object |
A |
probs |
Quantile probabilities. Default |
... |
Unused. |
An object of class "summary.dynamic_fit" containing posterior
summaries of the global parameters (params, one row per parameter) and
of the fitted values (fitted). The rows of params and the draws they
summarise are
innov_sdsqrt(draws$innov_var): the estimated increment SD
for "gaussian" innovations, the marginal SD for "t" and
"mixture", and the root of the series-average variance for "sv".
t_dfdraws$nu, the Student-t degrees of freedom.
sv_mu, sv_phi, sv_sigma
draws$sv_mu, draws$sv_phi and
draws$sv_sigma, the parameters of the AR(1) log-variance process.
ar1_rhodraws$rho, the AR(1) coefficient.
drift_mu / intercept_mu
draws$mu, the random-walk drift or
the AR(1) intercept.
gate_open_probdraws$pi_open, the probability that the
zero-inflation gate is open (one minus the structural-zero
probability).
Rows are included only where relevant. For "mixture" innovations only
innov_sd is reported. The mixture components are exchangeable and not
identified individually, so per-component summaries are not given. The
draws of the weights and component variances are in draws$mix_weight
and draws$mix_var. For the multinomial family every
latent parameter is reported once per non-baseline category, with the
category label in square brackets (e.g. innov_sd[B]), and the fitted
summary is a long data frame with a category column covering all K
categories.
sim <- simulate_dynamic_poisson(50, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 200, nburn = 100, seed = 1) summary(fit)sim <- simulate_dynamic_poisson(50, 0.2, 2, seed = 1) fit <- fit_dynamic_model(sim$y, nsave = 200, nburn = 100, seed = 1) summary(fit)
A weekly count series of irregular small-boat crossings of the English Channel towards the United Kingdom, covering the ISO weeks 2018-W01 to 2025-W11 (376 weeks). The series has frequent zeros in its early weeks (43% of the first 130 weeks), which makes it a useful example for zero inflation with the Poisson model. The series is used in the irregular-migration application of Zens and Bijak (2026).
uk_weeklyuk_weekly
A data frame with 376 rows and 3 variables:
ISO week label, e.g. "2018-W01".
Non-negative integer count of weekly crossings.
The Monday of the ISO week, as a Date.
Weekly aggregates of detected irregular English Channel crossings, compiled from operational/agency records as described in Zens and Bijak (2026), doi:10.1214/26-AOAS2171.
Zens, G. and Bijak, J. (2026). Dynamic Count Models with Flexible Innovation Processes for Irregular Maritime Migration. The Annals of Applied Statistics, 20(2), 1671–1690. doi:10.1214/26-AOAS2171.
plot(uk_weekly$date, uk_weekly$count, type = "h", xlab = "week", ylab = "crossings") mean(uk_weekly$count == 0)plot(uk_weekly$date, uk_weekly$count, type = "h", xlab = "week", ylab = "crossings") mean(uk_weekly$count == 0)