Introduction
This vignette describes the statistical model underlying sdmTMB. sdmTMB fits spatial and spatiotemporal generalized linear mixed models (GLMMs) using Template Model Builder (TMB) (Kristensen et al. 2016), with the model written in R through RTMB and spatial random fields approximated using the stochastic partial differential equation (SPDE) approach (Lindgren et al. 2011). Further details are available in the sdmTMB paper (Anderson et al. 2025), which should be referenced and cited when using sdmTMB in a publication.
If this vignette is being viewed on CRAN, note that many other vignettes describing how to use sdmTMB are available on the documentation site under Articles.
Notation conventions
This vignette uses the following notation conventions, which generally follow the guidance in Edwards & Auger-Méthé (2019):
Greek symbols for parameters and random effects, except for random intercepts and slopes to match lme4 and glmmTMB,
the Latin/Roman alphabet for data except for cases where another symbol is used by convention,
bold symbols for vectors or matrices (e.g., is a vector and is the value of at a point in space ), with Latin/Roman symbols in non-italics (e.g., , ),
for all distribution dispersion parameters for consistency with the code,
to define the expected value (mean) of variable ,
to define the variance of the variable ,
subscripts as shorthand for observation , which was sampled at location and time (several observations can share the same location and time),
a superscript represents values interpolated to observation or prediction locations as opposed to values at mesh vertices (e.g., vs. ), and
where possible, notation has been chosen to match VAST (Thorson 2019) to maintain consistency (e.g., for spatial fields and for spatiotemporal fields).
Tables of indices and symbols are summarized in notation reference tables at the end of this vignette.
sdmTMB model structure
An sdmTMB model combines relationships with measured predictors, variation across space and time, and an observation distribution describing variation around the expected response. For example, a model of species density might use depth as a predictor, a spatial field for persistent differences among locations, and a spatiotemporal field for spatial patterns that change from year to year. With a log link, a simple version is
Here, is the expected density conditional on the random fields. The spatial field describes spatial variation remaining after accounting for depth that persists through time, while describes additional spatial deviations that change through time. All terms on the right are on the log scale: a field value of doubles the expected density, holding the other terms constant. The observation distribution describes variation around this conditional mean. The fields describe spatial and spatiotemporal patterns, not their causes.
The general model structure is
where
- represents the response data at point and time ;
- represents the observation distribution (family) with parameter , dispersion parameter where applicable, and, for some families, additional parameters (e.g., the Tweedie power parameter);
- represents the family’s main parameter, which for most families is the conditional mean of the response (i.e., );
- represents a link function (e.g., log or logit) and represents its inverse;
- represents the linear predictor (i.e., in link space, before applying );
- , , and represent design matrices (the superscript identifiers ‘main’ = main effects, ‘tvc’ = time-varying coefficients, and ‘svc’ = spatially varying coefficients);
- represents a vector of fixed-effect coefficients;
- represents an offset: a covariate with a coefficient fixed at one that enters on the linear predictor scale (e.g., log effort with a log link);
- represents the vector of random intercepts and/or slopes for level of grouping factor (with being the level of factor for this observation) and the corresponding covariate values (a row of the random-effect design matrix );
- represents a vector of time-varying coefficients, where each coefficient can follow a random walk or AR(1) process;
- represents the values of the spatially varying coefficients at location , where each coefficient field is a Gaussian random field;
- represents a spatial random field, , with approximating a Matérn covariance via the SPDE approach (described below); and
- represents a spatiotemporal random field with IID, AR(1), or random walk dynamics through time; its spatial covariance is based on the Matérn model, and its marginal variance depends on the temporal process.
For binomial and beta-binomial counts, is a success probability and the count mean is . For truncated negative binomials, ordered beta, and mixture families, describes an underlying distribution or component rather than the full response mean; the family sections explain these distinctions. In the predictor equations, scalar field terms such as mean the field evaluated at the observation location. We use stars explicitly when distinguishing mesh-vertex values from their interpolated values (e.g., ).
Penalized smoothers are included in for brevity (their penalized coefficients are random effects; see Smoothers), and nonlocal (distributed lag) terms are omitted from the overview. Delta (hurdle) families have two linear predictors, each of which can contain the above components (see Delta models).
A single sdmTMB model will rarely, if ever, contain all of the above components.
Linear predictor components
This section describes each component of the linear predictor in more detail, using ‘’ to represent the other optional components.
Main effects
Within sdmTMB(),
is defined by the formula argument and represents the
main-effect model matrix and a corresponding vector of coefficients.
This main effect formula can contain optional penalized smoothers or
non-linear functions as defined below.
Smoothers
Smoothers in sdmTMB are implemented with the same formula syntax
familiar to mgcv (Wood 2017) users fitting
GAMs (generalized additive models). Smooths are implemented in the
formula using + s(x), which implements a smooth from
mgcv::s(). Within these smooths, the same syntax commonly
used in mgcv::s() can be applied, e.g. 2-dimensional
smooths may be constructed with + s(x, y); smooths can be
specific to various factor levels, + s(x, by = group);
smooths can vary according to a continuous variable,
+ s(x, by = x2); the basis function dimensions may be
specified, e.g. + s(x, k = 4) (see
?mgcv::choose.k); and various types of splines may be
constructed such as cyclic splines to model seasonality,
e.g. + s(month, bs = "cc", k = 12).
sdmTMB supports penalized smooths, which balance fit to the data
against excessive wiggliness. The function
mgcv::smooth2random() represents each supported smooth
using unpenalized coefficients and penalized coefficients treated as
random effects, with associated design matrices. This allows the smooth
to be estimated in a mixed-effects modelling framework. This is the same
approach as is implemented in the R packages gamm4 (Wood & Scheipl 2020) and brms (Bürkner 2017).
Linear break-point threshold models
The linear break-point or “hockey stick” model can be used to describe threshold or asymptotic responses. This function consists of two pieces, so that for , , and for , . Here, represents the slope of the function up to the threshold (break point) , and the product represents the value at the asymptote. No constraints are placed on or .
These models can be fit by including + breakpt(x) in the
model formula, where x is a covariate. The formula can
contain a single break-point covariate.
Logistic threshold models
Models with logistic threshold relationships between a predictor and the response can be fit with the form
where denotes the threshold function, is a scaling parameter (controlling the height and sign of the response curve; unconstrained), is an intercept, is the value of at which the function has reached 50% of its total change (), and is the value of at which it has reached 95% of its total change (). The parameter is unconstrained but is constrained to be larger than .
These models can be fit by including + logistic(x) in
the model formula, where x is a covariate. The formula can
contain a single logistic covariate.
Offset terms
Offset terms can be included through the offset argument
in sdmTMB(). These are included in the linear predictor
as
where
is an offset term—a variable on the linear predictor scale with its
coefficient fixed at one. With a log link, the offset is usually a
log-transformed measure of effort (e.g.,
log(area_swept)), so that
is proportional to effort.
When predicting, predict.sdmTMB() without
newdata uses the offset from the fitted model. With
newdata, the offset is 0 unless an offset
vector is supplied to predict.sdmTMB(). Therefore, if the
offset represents log effort, predictions on newdata are
for one unit of effort (log(1) = 0) by default.
Random intercepts and slopes
Multilevel (hierarchical) intercepts and slopes follow the familiar lme4/glmmTMB formulation. Each grouping factor can carry an intercept-only term or a vector of random effects (intercept plus slopes) with a full covariance matrix:
where
is the level of grouping factor
for the observation at
,
is the vector of random effects for that level, and
contains the corresponding covariate values (1 for an intercept and the
covariate value for each slope). Random effects are independent across
levels and grouping factors. The scalar special case
(1 | g) is a random intercept
.
Use lme4-style syntax in formula,
e.g. (1 | g) for random intercepts,
(1 + x | g) for correlated intercepts and slopes, or
(1 | g1) + (1 + x | g2) to give each grouping factor its
own (co)variance.
Internally, standard deviations are estimated on the log scale, and
correlations are represented by unconstrained parameters of a Cholesky
factor of the correlation matrix (TMB’s UNSTRUCTURED_CORR),
which guarantees a positive-definite
for each grouping factor.
Time-varying regression parameters
Parameters can be modelled as time-varying according to a random walk
or first-order autoregressive, AR(1), process. The time-series model is
defined by time_varying_type. For all types:
where
is an optional vector of time-varying regression parameters and
is the corresponding model matrix with covariate values. This is defined
via the time_varying argument, assuming that the
time argument is also supplied a column name.
time_varying takes a one-sided formula.
~ 1 implies a time-varying intercept.
The following equations describe the time-series process for a single time-varying coefficient , where indexes the time-varying coefficient. When multiple time-varying coefficients are specified, each follows its time-series process independently with its own variance parameter and (for AR1) correlation parameter .
For time_varying_type = 'rw', the initial value is
unpenalized (equivalent to an improper flat prior); only changes between
successive time steps receive a Gaussian penalty:
Because the initial value is estimated as part of the time-varying
formula, the same variable should not appear in the fixed-effects
formula. The formula time_varying = ~ 1 implicitly
represents a time-varying intercept (assuming the time
argument has been supplied) and, in this case, the intercept should be
omitted from the main-effects formula (e.g.,
formula = y ~ 0 + ... or
formula = y ~ -1 + ...).
For time_varying_type = 'rw0', the first time step is
estimated from a mean-zero prior:
In this case, the time-varying variable (including the intercept) should be included in the main effects.
For time_varying_type = 'ar1':
where
is the correlation between subsequent time steps. Here,
is the stationary marginal standard deviation; the innovation standard
deviation is
.
As with rw0, include the corresponding main effect to allow
a non-zero average coefficient.
Spatial random fields
Spatial random fields,
,
are included if spatial = 'on' (or TRUE) and
omitted if spatial = 'off' (or FALSE).
where
is the vector of field values at the mesh vertices. The marginal
standard deviation of
,
,
is indicated by Spatial SD in the printed model output or
as sigma_O in the output of
sdmTMB::tidy(fit, "ran_pars"). The ‘O’ is for ‘omega’
().
Internally, the random field is a Gaussian Markov random field (GMRF) defined by a sparse precision (inverse covariance) matrix :
depends on the mesh and on the parameters and , which determine the spatial range and (see Matérn parameterization).
Spatiotemporal random fields
Spatiotemporal random fields are included by default if there are
multiple time elements (time argument is not
NULL) and can be set to IID (independent and identically
distributed, 'iid'; default), AR(1) ('ar1'),
random walk ('rw'), or off ('off') via the
spatiotemporal argument. These text values are case
insensitive.
Spatiotemporal random fields are represented by
within sdmTMB. This has been chosen to match the representation in VAST
(Thorson 2019). The standard deviation
parameter
is indicated by Spatiotemporal SD in the printed model
output or as sigma_E in the output of
sdmTMB::tidy(fit, "ran_pars"). The ‘E’ is for ‘epsilon’
().
For IID and AR(1) fields, this is the marginal standard deviation; for a
random walk, it is the innovation standard deviation, as described
below.
IID spatiotemporal random fields
IID spatiotemporal random fields
(spatiotemporal = 'iid') can be represented as
where represents random field deviations at point and time . The random fields are assumed independent across time steps.
Similarly to the spatial random fields, these IID spatiotemporal random fields are parameterized internally with a sparse precision matrix (with parameters and )
AR(1) spatiotemporal random fields
First-order autoregressive, AR(1), spatiotemporal random fields
(spatiotemporal = 'ar1') add a parameter defining the
correlation between random field deviations from one time step to the
next. They are defined as
where
is the correlation between subsequent spatiotemporal random fields and
are IID spatial innovations. Because the first time step is drawn from
the stationary distribution and the
factor scales the innovations, every time step has the same marginal
variance,
;
the process is stationary. The correlation
allows for mean-reverting spatiotemporal fields, and is constrained to
be
.
Internally, the parameter is estimated as ar1_phi, which is
unconstrained. The parameter ar1_phi is transformed to
with
,
mapping ar1_phi to the range
.
Random walk spatiotemporal random fields (RW)
Random walk spatiotemporal random fields
(spatiotemporal = 'rw') represent a model where the
difference in spatiotemporal deviations from one time step to the next
are IID. They are defined as
where the distribution of the spatiotemporal field in the initial time step is the same as for the AR(1) model, but the absence of the parameter allows the spatiotemporal field to be non-stationary in time. A random walk has no stationary variance: under this initialization, , so the marginal variance grows with each time step. Therefore, is the standard deviation of the innovations (and of the field in the first time step), not the marginal standard deviation of the field in later time steps.
Spatially varying coefficients (SVC)
Spatially varying coefficient models are defined as
where
represents the value of the
-th
spatially varying coefficient field
at location
.
When multiple spatially varying coefficients are specified, each is
estimated as an independent spatial random field with its own marginal
variance
.
represents the corresponding design matrix for the spatially varying
coefficient terms, as defined by a one-sided formula supplied to
spatial_varying. For example
spatial_varying = ~ 0 + x, where 0 omits the
intercept. Because
is a mean-zero deviation, the main effect of x should
usually also be included in formula so that the coefficient
at location
is
.
The random fields are parameterized internally with a sparse precision matrix :
Each has its own (and therefore ) but shares with the spatial random field .
Nonlocal formula (covariate diffusion)
Nonlocal (distributed lag) terms let the effect of a covariate be
spread over nearby locations and/or previous time steps, rather than
acting only where and when the covariate was measured. This can be
useful when ecological responses are delayed, transported, or
accumulated through space and time. They are added with the
nonlocal_formula argument to sdmTMB() as a
one-sided formula using diffusion() (space) and/or
time_lag() (time) wrappers, e.g.,
~ diffusion(x) + time_lag(x). time_lag() terms
require a time argument. See (and cite) Lindmark et al. (2025) for the spatial
diffusion model and Thorson et al.
(2026) for the extension to time; those papers give the full
formulation and guidance on interpretation.
Each covariate
in nonlocal_formula is transformed into a smoothed
covariate
,
which enters the linear predictor with an estimated coefficient:
If the same covariate appears in both wrappers, as in
~ diffusion(x) + time_lag(x), both apply to one transformed
covariate with one coefficient. If the covariates differ, as in
~ diffusion(x1) + time_lag(x2), the model has two
transformed covariates and two coefficients.
For diffusion(x), the covariate at time
,
(evaluated at the mesh vertices), is smoothed in space by solving
where
and
are the SPDE mass and stiffness matrices (see Matérn parameterization) and
controls the spatial scale of the diffusion. The output reports this
scale as RMSDK (the root-mean-squared displacement of the
diffusion kernel,
,
in the units of the mesh coordinates).
For time_lag(x), the covariate at each vertex is an
exponentially weighted average of current and past values:
By default, time_lag(x) uses
start = "stationary", assuming that the covariate held its
first observed value before the series began:
.
Use time_lag(x, start = "zero") for
.
The choice affects the transformed covariate near the start of the
series. Larger
means a longer memory of past covariate values.
When both wrappers are applied to the same covariate, spatial
smoothing and temporal propagation act on the same evolving field (this
corresponds to kappaST = 0 in Thorson et al. (2026)), and the
reported MSDK and RMSDK account for both. With
both wrappers, the stationary initial value is the spatially smoothed
first covariate slice. A separate
is estimated for each covariate with spatial diffusion, and a separate
for each covariate with a temporal lag.
Gaussian random fields
This section describes how the spatial (), spatiotemporal (), and spatially varying coefficient () random fields are constructed. How each field enters the model is described under Linear predictor components.
Interpreting range and standard deviation
A spatial random field is a collection of random effects whose values are correlated across locations. For the usual isotropic Matérn model, correlation depends on distance, with nearby locations more strongly correlated than distant ones. The range describes the distance over which this correlation declines: at one range, correlation is approximately 0.13, not zero. The marginal standard deviation describes the typical size of field deviations at a location, on the link scale. A larger range produces broader spatial patterns; a larger standard deviation allows larger departures from the predictor effects. For spatiotemporal fields, the reported standard deviation describes the field itself under IID or AR(1) dynamics, but the changes between time steps under a random walk.
In a model with both spatial and spatiotemporal fields,
share_range = TRUE (the default) estimates a common range
with separate standard deviations for the two fields. Sharing a range
can be useful when the data contain limited information about separate
ranges. Use share_range = FALSE to estimate separate
ranges. Spatially varying coefficient fields share the spatial
range.
The following construction details are optional for understanding the model components and interpreting these parameters.
Matérn parameterization
For continuous-space models without barriers, sdmTMB approximates Gaussian random fields with Matérn spatial covariance. The Matérn covariance between the field values at locations and , separated by distance , is
where is the marginal variance, controls the smoothness of the field, is the gamma function, is the modified Bessel function of the second kind, and is a scaling parameter (larger means correlation decays faster with distance).
Computing with a dense Matérn covariance matrix is slow for many locations. Instead, sdmTMB uses the stochastic partial differential equation (SPDE) approach of Lindgren et al. (2011). A Gaussian field with Matérn covariance is the solution to the SPDE , where is the Laplacian, is Gaussian white noise, and for spatial dimensions. sdmTMB uses and , so . Approximating the solution on a triangulated mesh with piecewise-linear basis functions (the finite element method) gives field values at the mesh vertices with a sparse precision matrix
where is a diagonal approximation to the finite-element mass matrix (called mass lumping), and is a sparse stiffness matrix. Both matrices depend only on the mesh. The sparsity of (most entries are zero) is what makes the computations fast.
The parameters and determine the reported range and marginal standard deviation:
These relationships describe the stationary Matérn field; the finite mesh and its boundaries introduce approximation error. For a fixed , increasing decreases . Sharing a range means sharing , while separate parameters allow different field standard deviations. Throughout, , , and denote full precision matrices, including the scaling (the code applies this scaling separately when evaluating the field densities).
Projection matrix
In the SPDE approach, the random field at any location is defined by the piecewise-linear basis expansion , where is the field value at mesh vertex and is a “tent” function that is 1 at vertex and decreases linearly to 0 at the neighbouring vertices. Evaluating the field at observed or prediction locations is therefore a multiplication by a sparse projection matrix with elements (Lindgren & Rue 2015):
where represents the values of the spatial random fields at the observed locations or predicted data locations. The matrix has a row for each data point or prediction point and a column for each mesh vertex. Each row has at most three non-zero elements: the barycentric weights of the vertices of the triangle containing that location. This interpolation is part of the model definition rather than a separate approximation step. The same interpolation happens for any spatiotemporal random fields
Anisotropy
TMB allows for anisotropy, where spatial covariance may depend on
direction (full
details). Anisotropy can be turned on or off with the logical
anisotropy argument to sdmTMB(). There are a
number of ways to implement anisotropic covariance (Fuglstad et al. 2015), and we adopt
geometric anisotropy defined by a 2-parameter matrix
,
which replaces Euclidean distance with
.
The elements of
are defined by the parameters
and
so that
,
and
.
is symmetric and positive definite with determinant 1, so it stretches
distances along one axis and shrinks them along the perpendicular axis
without changing area. The result is a different range in each
direction, with the orientation of the major axis estimated.
Once a model is fitted with sdmTMB(), the anisotropy
relationships may be plotted using the plot_anisotropy()
function, which takes the fitted object as an argument. If a barrier
mesh is used, anisotropy is disabled.
Incorporating physical barriers into the SPDE
In some cases the spatial domain of interest may be complex and
bounded by some barrier such as by land or water (e.g., coastlines,
islands, lakes). SPDE models allow for physical barriers to be
incorporated into the modelling (Bakka et
al. 2019). With sdmTMB() models, the mesh
construction occurs in two steps: the user (1) constructs a mesh with a
call to sdmTMB::make_mesh(), and (2) passes the mesh to
sdmTMBextra::add_barrier_mesh(). The barriers must be
constructed as sf objects (Pebesma
2018) with polygons defining the barriers. See
?sdmTMBextra::add_barrier_mesh for an example.
The barrier implementation requires the user to select a fraction
value (range_fraction argument) that defines the fraction
of the usual spatial range when crossing the barrier (Bakka et al. 2019). For example, if
the range was estimated at 10 km, range_fraction = 0.2
would assign a 2 km range to the triangles marked as barrier. That makes
correlation decay much faster through the barrier than around it, which
effectively discourages spatial smoothing from “jumping” across
landmasses. From experimentation, values around 0.1 or 0.2 seem to work
well but values much lower than 0.1 can result in convergence issues.
The range_fraction is fixed, not estimated.
Following Bakka et al. (2019), the barrier model lets the range vary in space through the SPDE
where
is the gradient,
in the normal part of the domain and
range_fraction in barrier triangles. With a constant range
,
this is the Matérn SPDE given above, with marginal standard deviation
.
With barriers, the field is no longer a stationary Matérn field, so its
precision matrix is not the
given above. sdmTMB builds it with the formulation used in the INLAspacetime
package, parameterized directly by the range and marginal standard
deviation. The reported range is still
,
and
is still computed from
and
as above. Both describe the field away from barriers; near barriers, the
variance and correlation are modified.
This website by Francesco Serafini and Haakon Bakka provides an illustration with INLA. The original TMB implementation in sdmTMB was adapted from code written by Olav Nikolai Breivik and Hans Skaug at the TMB Case Studies GitHub site.
Areal autoregressive models (SAR/CAR)
In addition to continuous-space SPDE random fields, sdmTMB can fit
areal spatial autoregressive models with
spatial_model = "sar" or
spatial_model = "car". These require an areal domain
supplied to mesh with the help of
make_areal_domain().
For both areal options, the latent spatial and spatiotemporal effects are Gaussian Markov random fields with precision defined by the areal weight matrix . For the spatial field and IID or AR(1) spatiotemporal fields,
For a random walk, instead describes the covariance of the initial field and subsequent innovations. Unlike the SPDE case, and here are scale parameters, not marginal standard deviations: the diagonal entries of depend on and the autocorrelation parameter and generally differ among areas.
For SAR (spatial_model = "sar"), the precision matrix
is
where
is reported as rho_sar. By default, SAR uses a
row-normalized
(sar_weight_style = "row"), with an option to use raw
weights. With sar_weight_style = "raw", SAR uses the
unnormalized adjacency/weight matrix directly, so neighbour influence
depends on the original edge weights (and, if unweighted, on the number
of neighbours) rather than being scaled to sum to 1 within each row.
For CAR (spatial_model = "car"), the precision matrix
is
where
is diagonal with elements
(the number of neighbours for unweighted adjacency; set to 1 for areas
with no neighbours) and
is reported as alpha_car. CAR requires a symmetric
adjacency matrix.
Observation model families
Here we describe the main observation families that are available in sdmTMB and comment on their parametrization, statistical properties, utility, and code representation in sdmTMB. Families are grouped by outcome type to make it easier to locate an appropriate observation model.
Bounded or binary outcomes (0–1, proportions)
Binomial
where
is the size or number of trials, and
is the probability of success for each trial. If
,
the distribution becomes the Bernoulli distribution. Internally, the
distribution is parameterized as the robust
version in TMB, which is numerically stable when probabilities
approach 0 or 1. Following the structure of stats::glm(),
lme4, and glmmTMB, a binomial family can be specified in one of 4
ways:
- the response may be a factor (and the model classifies the first level versus all others)
- the response may be binary (0/1)
- the response can be a matrix of form
cbind(success, failure), or - the response may be the observed proportions, and the
weightsargument is used to specify the Binomial size () parameter (probability ~ ..., weights = N).
Code defined within TMB.
Example: family = binomial(link = "logit")
Beta-binomial
where is the number of trials, is the mean success probability, and is a precision parameter that controls overdispersion relative to a Binomial distribution. The implied Beta parameters are and , and the variance is
For and , this exceeds the Binomial variance for finite and approaches it as . For , the distribution reduces to Bernoulli. Available links are logit and cloglog. This family is useful for overdispersed counts of successes/failures (e.g., aggregated Bernoulli data, proportions with extra-binomial variation).
Code defined within sdmTMB.
Example: family = betabinomial(link = "logit")
Beta
where is the mean and is a precision parameter. This parametrization follows Ferrari & Cribari-Neto (2004) and the betareg R package (Cribari-Neto & Zeileis 2010). The variance is .
Code defined within TMB.
Example: family = Beta(link = "logit")
Ordered beta
The ordered beta distribution (Kubinec 2023) is for continuous proportions on the closed interval that include exact zeros and/or ones. A single linear predictor and two estimated cutpoints define and , and values in follow with . Here, is the mean conditional on ; the full response mean is . It is a parsimonious alternative to zero-one-inflated beta models because all three components share one linear predictor.
Example: family = ordbeta(link = "logit")
Count data
Poisson
where represents the mean and .
Code defined within TMB.
Example: family = poisson(link = "log")
Censored Poisson
A Poisson distribution in which some observations are censored: the
true count is only known to lie in the interval
,
where
may be infinite (right censoring). The likelihood of a censored
observation is
under
.
Upper bounds are supplied with
sdmTMBcontrol(censored_upper = ...), where NA
indicates no upper bound and a value equal to
indicates an uncensored observation. Watson
et al. (2023) developed this approach to account for
hook competition in longline surveys, where observed catch counts are
lower bounds on what would have been caught in the absence of
competition for baited hooks. See the hook
competition article for a worked example.
Example: family = censored_poisson(link = "log")
Negative Binomial 2 (NB2)
where is the mean and is the dispersion parameter. The variance scales quadratically with the mean (Hilbe 2011). The NB2 parametrization is more commonly seen in ecology than the NB1. Internally, the distribution is parameterized as the robust version in TMB.
Code defined within TMB.
Example: family = nbinom2(link = "log")
Negative Binomial 1 (NB1)
where is the mean and is the dispersion parameter. The variance scales linearly with the mean (Hilbe 2011). Internally, the distribution is parameterized as the robust version in TMB.
Code defined within sdmTMB based on NB2 and borrowed from glmmTMB.
Example: family = nbinom1(link = "log")
Truncated negative binomial
Zero-truncated versions of the NB2 and NB1 distributions, for
positive counts
().
Here,
is the mean of the untruncated distribution; the mean of the truncated
distribution is
.
These are mainly used as the positive component of delta models for
counts (e.g., delta_truncated_nbinom2()).
Example: family = truncated_nbinom2(link = "log") or
family = truncated_nbinom1(link = "log")
Negative binomial 2 mixture
This is a 2 component mixture that extends the NB2 distribution, following mixture-distribution approaches for aggregation (e.g., schooling) in survey data (Thorson et al. 2011).
where is the mean of the smaller component, is the mean of the larger component for an estimated ratio , and is the probability of the larger component. The full response mean is .
Example: family = nbinom2_mix(link = "log")
Positive continuous outcomes
Gamma
where represents the Gamma shape and represents the scale. The mean is and variance is .
Code defined within TMB.
Example: family = Gamma(link = "log")
Lognormal
sdmTMB uses the “bias-corrected” lognormal distribution where represents the standard deviation in log-space:
Because of the bias correction, and .
Code defined within
sdmTMB based on the TMB dnorm() normal density.
Example: family = lognormal(link = "log")
Generalized gamma
sdmTMB implements the Prentice (1974)
parameterization introduced for spatiotemporal models and index
standardization by Dunic et al.
(2025), with parameters mean
,
scale
,
and a shape parameter
(reported as Generalized gamma Q).
Here,
is the mean on the data scale,
is a scale parameter that equals the log-scale standard deviation in the
lognormal limit, and
controls the shape
(
yields the lognormal;
yields the gamma). See Dunic et al.
(2025) for the full PDF in the Prentice formulation as
implemented. Links available: identity, log, inverse. This flexibility
is useful for right-skewed positive responses with tails heavier or
lighter than gamma/lognormal, and is often paired in a hurdle/mixture as
delta_gengamma() for zero-inflated biomass or catch data
(see Dunic et al. (2025)).
Code defined within sdmTMB.
Example: family = gengamma(link = "log"); delta/hurdle:
family = delta_gengamma(link1 = "logit", link2 = "log").
Gamma mixture
This is a 2 component mixture that extends the Gamma distribution, motivated by mixture-distribution treatments of aggregation in survey data (Thorson et al. 2011),
where represents the Gamma shape, represents the scale for the first (smaller component) of the distribution, represents the scale for the second (larger component) of the distribution, and controls the contribution of each component to the mixture (also interpreted as the probability of larger events).
As with the NB2 mixture, and for an estimated ratio . The full response mean is . The variance follows the usual mixture formula: .
Here, and for the other mixture distributions, the probability of the
larger mean can be obtained from
plogis(fit$model$par[["logit_p_extreme"]]) and the ratio of
the larger mean to the smaller mean can be obtained from
1 + exp(fit$model$par[["log_ratio_mix"]]). The standard
errors are available in the TMB sdreport:
fit$sd_report.
If you wish to fix the probability of a large (i.e., extreme) mean, which can be hard to estimate, you can fix this value and pass this to the family:
See also family = delta_gamma_mix() for an extension
incorporating this distribution with delta models.
Lognormal mixture
This is a 2 component mixture that extends the lognormal distribution, again in the spirit of mixture approaches for aggregating/schooling data (Thorson et al. 2011),
As with the other mixtures, with , and the full response mean is (the terms make each component’s mean ). The log-scale variance of the mixture is not simply ; it can be obtained with the standard mixture-variance formula using component log-means and log-variance .
As with the Gamma mixture, controls the contribution of each component to the mixture (also interpreted as the probability of larger events).
Example: family = lognormal_mix(link = "log"). See also
family = delta_lognormal_mix() for an extension
incorporating this distribution with delta models. Like with the gamma
mixture, fixed probabilities of extreme events
(
in notation above) can be passed in, e.g.
sdmTMB(...,
family = delta_lognormal_mix(p_extreme = 0.01)
)Non-negative continuous outcomes with exact zeros
Tweedie
where is the mean, is the power parameter constrained between 1 and 2, and is the dispersion parameter. The Tweedie distribution (a compound Poisson-gamma distribution for ) can be helpful for modelling data that are non-negative and continuous with exact zeros. The variance is . Delta models are an alternative that model zeros and positive values with separate linear predictors.
Internally,
,
which constrains it between 1 and 2, and thetaf is
estimated as an unconstrained parameter.
The source code is implemented as in the cplm package (Zhang 2013) and is based on Dunn & Smyth (2005). The TMB version is defined here.
Example: family = tweedie(link = "log")
Continuous real-valued outcomes
Gaussian
where is the mean and is the standard deviation. The variance is .
Example: family = gaussian(link = "identity")
Code defined within TMB.
Student-t
where
is the location (mean for
),
is a scale parameter (not the standard deviation; the variance is
for
),
and
,
the degrees of freedom (df), is estimated by default and
can optionally be fixed by the user. Lower values of
result in heavier tails compared to the Gaussian distribution. Above
approximately df = 20, the distribution becomes very
similar to the Gaussian. The Student-t distribution with a low degrees
of freedom (e.g.,
)
can be helpful for modelling data that would otherwise be suitable for
Gaussian but needs an approach that is robust to outliers (e.g., Anderson et al. 2017).
Code defined within
sdmTMB based on the dt() distribution in TMB.
Example: family = student(link = "identity", df = 7)
Delta models
sdmTMB allows for several different kinds of delta (also known as hurdle) models. These families are implemented by specifying the family as a delta distribution. For example:
sdmTMB(
...,
family = delta_gamma()
)The list of supported families is included in the documentation on additional
families, delta
models, and Poisson-link
delta models. By default, the delta_* families don’t
use the Poisson link, but this structure can be specified with
delta_gamma(type = "poisson-link"), which follows the
formulation in Thorson (2018).
In the “standard” delta model implementation, sdmTMB constructs two
internal models (formally, two “linear predictors”), with the first
model representing presence-absence and the second model representing
the positive component (such as catch rates in fisheries applications).
The positive component can be continuous (e.g.,
delta_gamma(), delta_lognormal(),
delta_gengamma()), a proportion in
(delta_beta()), or a positive count from a zero-truncated
negative binomial (delta_truncated_nbinom2(),
delta_truncated_nbinom1()). The expected value is the
product of the probability of a non-zero observation and the expected
value of the positive component. Default links associated with each
family can be inspected with delta_lognormal() and
equivalent functions. For the standard delta models, the default first
linear predictor link is logit. For the Poisson-link type, the first
linear predictor link is log.
The formula, spatial,
spatiotemporal, and share_range arguments of
sdmTMB() can be specified independently as a 2-element
list. For example, the spatial random field might be estimated for only
the first linear predictor with:
sdmTMB(
...,
family = delta_gamma(),
spatial = list("on", "off")
)Or we may want separate main-effects formulas. For example:
sdmTMB(
formula = list(
y ~ depth + I(depth^2),
y ~ 1),
family = delta_gamma()
)All other arguments are shared between the linear predictors.
Currently if delta models contain smoothers, both components must have the same main-effects formula.
Optimization
Optimization details
By default, sdmTMB fits models by maximum marginal likelihood: the
likelihood is integrated over the random effects, accounting for their
uncertainty when estimating the remaining parameters. These remaining
parameters include regression coefficients, variance and correlation
parameters, spatial ranges, and observation-distribution parameters. We
call them the outer parameters below because they are optimized
in an outer loop, while the random effects are optimized in an inner
loop for each candidate set of outer-parameter values. TMB and glmmTMB
call these ‘fixed effects’, which includes the variance parameters, not
just the regression coefficients. With reml = TRUE, the
regression coefficients are also integrated out, together with the
random effects. The joint likelihood is written with RTMB (the default
backend; a C++ TMB template can be used instead with
sdmTMBcontrol(backend = "tmb")), and Template Model Builder
(TMB) (Kristensen et al. 2016)
uses automatic differentiation and the Laplace approximation to
integrate over the random effects. This yields an approximation to the
marginal log likelihood of the outer parameters and its gradient, and
the negative marginal log likelihood is minimized with the non-linear
optimization routine stats::nlminb() in R (Gay 1990; R Core Team 2021). For given
outer-parameter values, the random effects are set to the values that
maximize the joint log likelihood (their conditional modes), around
which the Laplace approximation is taken (Kristensen et al. 2016).
Like AD Model Builder (Fournier et
al. 2012), sdmTMB fits parameters in phases by default
(multiphase = TRUE in
sdmTMB::sdmTMBcontrol()). Phased estimation is usually
faster and more stable, but not always, because it requires building the
model an extra time. In sdmTMB, the first phase holds random effects at
their initial values and estimates the regression and
observation-distribution parameters to obtain starting values. The
second phase fits the full model, using the first-phase estimates as
starting values and estimating the random effects and their variance and
correlation parameters as well.
In some cases, a single call to stats::nlminb() may not
result in convergence (e.g., the maximum gradient of the marginal
likelihood with respect to the outer parameters is not small enough
yet), and the algorithm may need to be run multiple times. In the
sdmTMB::sdmTMBcontrol() function, we include an argument
nlminb_loops that will restart the optimization at the
previous best values. The number of nlminb_loops should
generally be small (e.g., 2 or 3), and defaults to 1. After
stats::nlminb(), sdmTMB takes Newton steps to further
reduce the gradient: it computes the Hessian
of the negative marginal log likelihood numerically with
stats::optimHess() and updates the outer parameters
as
,
where
is the gradient. The number of Newton steps is set with
newton_loops in sdmTMB::sdmTMBcontrol()
(default 1). A step is only accepted if it does not increase the
negative marginal log likelihood. If a model is already fit, the
function sdmTMB::run_extra_optimization() can run
additional optimization loops with either routine to further reduce the
maximum gradient.
Assessing convergence
The sanity() function runs a set of basic convergence
checks on a fitted model (e.g., the Hessian is positive definite,
gradients are small, standard errors are not NA or very
large, and random field variances have not collapsed to zero) and is a
good first step. Much of the guidance around diagnostics and glmmTMB
also applies to sdmTMB, e.g. the glmmTMB vignette
on troubleshooting. Optimization with stats::nlminb()
involves specifying the number of iterations and evaluations
(eval.max and iter.max) and the tolerances
(abs.tol, rel.tol, x.tol,
xf.tol)—a greater number of iterations and smaller
tolerance thresholds increase the chance that the optimal solution is
found, but more evaluations translates into longer computation time.
Warnings of non-positive-definite Hessian matrices (accompanied by
parameters with NAs for standard errors) often mean models
are improperly specified given the data. Standard errors can be observed
in the output of print.sdmTMB() or by checking
fit$sd_report. The maximum gradient of the marginal
likelihood with respect to the outer parameters can be checked by
inspecting fit$gradients. Guidance varies, but gradients
should be very close to zero (e.g., on the order of
or smaller after reasonable parameter scaling) before assuming the
fitting routine is consistent with convergence. If maximum gradients are
already relatively small, they can sometimes be reduced further with
additional optimization calls beginning at the previous best parameter
vector as described above with
sdmTMB::run_extra_optimization().
Notation reference tables
Tables of all major indices (Table 1) and symbols (Table 2) are provided here for quick reference.
| Symbol | Description |
|---|---|
| Index for space; a vector of x and y coordinates | |
| Index for time | |
| Level of a random-effect grouping factor | |
| Random-effect grouping factor | |
| Index for time-varying coefficient | |
| Index for spatially varying coefficient (SVC) |
| Symbol | Code | Description |
|---|---|---|
y_i |
Observed response data | |
mu |
Inverse-linked family parameter (usually the conditional response mean) | |
eta_i |
Linear predictor before applying the inverse link () | |
phi |
A dispersion parameter for a distribution (estimated as
ln_phi) |
|
fit$family$link |
Link function | |
fit$family$linkinv |
Inverse link function | |
b_j |
Fixed-effect coefficient vector | |
X_ij |
A predictor model matrix | |
Zt_list |
Random effect design matrix; is the row for one observation and grouping factor | |
offset_i |
An offset variable at point and time | |
omega_s |
Spatial random field at point (vertex) | |
omega_s_A |
Spatial random field at point (interpolated) | |
zeta_s |
Spatially varying coefficient random field at point (vertex) | |
zeta_s_A |
Spatially varying coefficient random field at point (interpolated) | |
epsilon_st |
Spatiotemporal random field at point and time (vertex) | |
epsilon_st_A_vec |
Spatiotemporal random field at point and time (interpolated) | |
| - | AR(1) or random walk spatiotemporal innovations (vertex) | |
b_rw_t |
Time-varying coefficients | |
re_b_pars |
Vector of random intercepts/slopes for level of grouping factor | |
| - | Spatial random field covariance matrix | |
| - | Spatially varying coefficient random field covariance matrix | |
| - | Spatiotemporal marginal covariance (IID/AR1) or innovation covariance (RW) | |
Q |
Spatial random field precision matrix (code omits ) | |
Q |
Spatially varying coefficient precision matrix; shares , with its own (code omits ) | |
Q_st |
Spatial precision matrix of the spatiotemporal process;
Q if the range is shared (code omits
) |
|
re_cov_pars |
Random effect covariance matrix for grouping factor (log SDs and correlation parameters) | |
sigma_O |
Spatial marginal SD for SPDE fields; scale parameter for SAR/CAR | |
sigma_E |
Spatiotemporal marginal SD (IID/AR1) or innovation SD (RW); scale parameter for SAR/CAR | |
sigma_Z |
Spatially varying coefficient marginal SD for SPDE fields; scale parameter for SAR/CAR | |
sigma_V |
Time-varying coefficient innovation SD (RW/RW0) or stationary marginal SD (AR1) | |
ln_tau_O, ln_tau_E,
ln_tau_Z
|
SPDE precision scaling parameters (log scale) | |
kappa[1, ] |
Spatial Matérn scaling parameter (estimated as
ln_kappa) |
|
kappa[2, ] |
Spatiotemporal Matérn scaling parameter | |
range |
Distance at which correlation drops to approximately 0.13 | |
rho |
Correlation between spatiotemporal random fields in
subsequent time steps (estimated as ar1_phi) |
|
rho_time |
Correlation between time-varying coefficients in subsequent time steps | |
rho_sar |
SAR spatial autocorrelation parameter | |
alpha_car |
CAR spatial autocorrelation parameter | |
| , |
s_slope, s_cut
|
Breakpoint slope and break point |
| , , |
s50, s95,
s_max
|
Logistic threshold parameters |
| , |
kappaS_nl, kappaT_nl
|
Nonlocal (distributed lag) spatial and temporal scale parameters |
| (Tweedie) | tweedie_p |
Tweedie power parameter (estimated as
thetaf) |
student_df |
Student-t degrees of freedom | |
gengamma_Q |
Generalized gamma shape parameter ( gives lognormal; gives gamma) | |
| , | psi |
Ordered beta cutpoints |
| (mixture) | p_extreme |
Probability of the larger mixture component |
A_station |
Sparse projection matrix to interpolate from mesh vertices to the unique data or prediction locations | |
H |
2-parameter matrix defining geometric anisotropy
(estimated as ln_H_input) |
