Skip to content

sdmTMB

1.2.0Package record

Spatial and Spatiotemporal SPDE-Based GLMMs with 'TMB'

1packages dependsuggested by 3
65.6Kdownloads / year
87.9%test coverage
13/13flavors OK

Overview

About

Implements spatial and spatiotemporal GLMMs (Generalized Linear Mixed Effect Models) using 'TMB', 'fmesher', and the SPDE (Stochastic Partial Differential Equation) Gaussian Markov random field approximation to Gaussian random fields. One common application is for spatially explicit species distribution models (SDMs). See Anderson et al. (2025) doi:10.18637/jss.v115.i02.

Changes in 1.2.0

Breaking changes

  • Removed the previously deprecated delta_poisson_link_gamma() and delta_poisson_link_lognormal(). Use delta_gamma(type = "poisson-link") or delta_lognormal(type = "poisson-link").
  • Removed the previously deprecated extract_mcmc() and add_barrier_mesh() functions; use the versions in sdmTMBextra. Also removed the previously deprecated previous_fit argument of simulate_new() (use simulate.sdmTMB()).
  • sdmTMB_cv() now scores held-out data with a predictive density integrated over the approximate posterior of the random effects (predictive = "mle-mvn") instead of at their estimated values ("mle-eb"). predictive = "joint" also integrates over the fixed effects and variance parameters. nsim sets the number of draws per fold, so sum_loglik now depends on the random seed. The "mle-eb" values are always returned in cv_loglik_mle_eb and sum_loglik_mle_eb. Random field uncertainty on out-of-sample predictions generally increases with more spatial knots, so it becomes increasingly important to account for random field uncertainty at finer mesh resolutions and it's particularly important for comparing across mesh resolutions.
Show all changes in 1.2.0Hide the rest of the changes in 1.2.0
  • get_index_split() now defaults to bias_correct = TRUE, matching get_index().
  • predict(allow_new_levels = FALSE) now gives an error for new levels of a random effect grouping factor, as in lme4 and glmmTMB. Previously it gave the same warning as the default (NULL).
  • The arguments of sdmTMB() after family are reordered into groups: core model, observation-level adjustments, field configuration, additional model structure, specialized response options, estimation, and deprecated arguments. Code that passes arguments after family by position must name them.
  • Censoring bounds for censored_poisson() and censored_betabinomial() are now supplied with the censored_upper argument of sdmTMB(), which also accepts a column name in data. The censored_upper argument of sdmTMBcontrol() has been removed. Use Inf instead of NA for no upper bound; NA is deprecated and is treated as Inf with a warning. get_censored_upper() now caps the bounds at the number of hooks. This also fixes sdmTMB_cv() misaligning the bounds with the data when folds were assigned randomly with a time column.
  • predict.sdmTMB() now errors for type = "response" with se_fit = TRUE (previously a warning, with link-scale output) and with a sims_var other than "est". Use type = "link" for standard errors or nsim for response-scale uncertainty. sims_var accepts only "est", "omega_s", "zeta_s", "epsilon_st", "est_rf", and "est_non_rf"; use return_tmb_report = TRUE with nsim for other reported variables.
  • diffusion(x) + time_lag(x) in nonlocal_formula now fits one stationary joint space--time distributed-lag operator with one coefficient. Temporal persistence is constrained to be non-negative. The temporal parameter is estimated as log_kappaT_nl (equal to logit(rhoT)) rather than kappaT_nl_raw, sdmTMB_simulate() requires 0 < lags_rhoT < 1, and the derived summaries are named MSDK and RMSDK rather than MSD and RMSD.
  • time_lag() now starts from a stationary state by default (the covariate is assumed to have held at its first time slice); use start = "zero" for the previous behaviour, which matches Thorson et al. (2026).
  • spatial_varying now respects its own model matrix, and the (Intercept) column is dropped only when spatial = "on". For spatial = "off", spatial_varying = ~ 1 + factor, the model now fits a genuine intercept field plus K - 1 deviation fields instead of omitting the reference field, with a one-time warning. The svc-factor-models article clarifies how spatial, spatial_varying, and the intercept of the spatial_varying design matrix interact.
  • For truncated_nbinom1() and truncated_nbinom2(), phi now comes from each fit's own parameters rather than the family object, so calling family$linkinv() directly for these families requires phi.
  • The experimental epsilon_model and epsilon_predictor options are removed and now error. File an issue if you're interested in using this functionality and we can consider adding it back.

New features

  • **RTMB is now the default backend.** The model code is written in R (via RTMB) with about 50% fewer lines, and gives the same results as the TMB backend in all our tests, although simulated values differ between backends for the same seed. The TMB backend is retained for now but will eventually be dropped. To keep using it, set control = sdmTMBcontrol(backend = "tmb") per fit or options(sdmTMB.backend = "tmb") per session. The move uncovered several bugs, which are fixed as listed below, and allowed for optimization of the model. Speedups relative to sdmTMB 1.1.0 on an example model with the built-in pcod dataset:
  • fitting: 1.2x
  • predict(): 13.5x
  • get_index(bias_correct = FALSE): 10.4x
  • get_index(bias_correct = TRUE): 1.5x
  • simulate(nsim = 400): 1.9x
  • project(nsim = 400) (30-year AR1 projection): 9.3x
  • simulate_new() now works with areal SAR/CAR models: pass an areal domain from make_areal_domain() as mesh, set spatial_model = "sar" or "car", and supply rho_sar or alpha_car instead of range. #552
  • Added lognormal_prior() as an option for sdmTMBpriors(sigma_V = ...) priors on time-varying coefficient SDs.
  • simulate.sdmTMB() gains a simulate_re argument to choose which random effects are simulated as new (any of "spatial", "spatiotemporal", "spatial_varying", "group_re", "time_varying"). Random effects not named are held at their empirical Bayes estimates (type = "mle-eb") or at an approximate posterior draw (type = "mle-mvn"). For example, simulate_re = "spatiotemporal" with type = "mle-mvn" holds the spatial fields at one posterior draw while simulating new spatiotemporal fields.
  • Add custom priors for the RTMB backend: sdmTMBpriors(custom = function(par, theta) ...) adds arbitrary log densities on raw (par) or natural-scale (theta) parameters, including random effects, to the joint objective. With bayesian = TRUE, custom_log_jacobian supplies the matching Jacobian adjustment. New get_prior_parameters() lists the available parameters and get_prior_densities() evaluates the terms at the estimates. See the new vignette "Custom priors and penalties".
  • Add experimental multi-family models, where each row of the data can use a different observation family (e.g., binomial, count, and delta-lognormal data in one model with shared fields). Supply a named list to family and name the column mapping rows to families with distribution_column. See the new multi-family vignette/article.
  • Add ordbeta() for ordered beta regression (Kubinec 2023), an alternative to zero-one-inflated beta for continuous data on [0, 1] with point masses at 0 and 1 (#515). Response-scale predictions and indices include the point masses.
  • Add censored_betabinomial() for censored beta-binomial counts, e.g., to account for hook competition in hook-and-line surveys with the number of hooks as the number of trials. It uses sdmTMB(censored_upper = ...) like censored_poisson(), with Inf meaning censoring between the observed count and the number of trials. It needs the RTMB backend. The likelihood sums the shorter of each interval and its complement, with a precision check and fallback to the direct sum after fitting (sdmTMBcontrol(censored_method = "direct") forces the direct sum). See the new article "Accounting for hook competition with censored count models".
  • Add censored_binomial() for censored binomial counts. It works like censored_betabinomial() (RTMB backend, number of trials via weights). With link = "cloglog" and an observation-level random intercept, it is a Poisson-lognormal model of the per-hook catch rate with at most one fish per hook, so get_index(derived_link = "log") is proportional to the mean catch rate.
  • Add censored_nbinom1() and censored_nbinom2() for censored negative binomial counts (RTMB backend). They use sdmTMB(censored_upper = ...) like censored_poisson(), with no upper limit on the count, e.g., for catch without hook competition with an offset of log hooks.
  • Add the dispformula argument to sdmTMB() for modelling the observation dispersion parameter with fixed-effect predictors. It is not supported for multi-family models or truncated negative binomial families.
  • Add compare_deviance() for deviance explained (a pseudo-R^2) relative to a simpler model.
  • Add a loo::elpd() method for sdmTMB_cv() output so models can be compared with loo::loo_compare(), including a standard error of the difference. See ?sdmTMB_cv for an example.
  • Add deviance residuals and deviance() for gengamma() and censored_poisson().
  • Add make_zero_one_map() for categories (e.g., year factors) where the response is all zeros or ones. #386
  • Add sample_fe argument to predict.sdmTMB(). With nsim > 0 and sample_fe = FALSE, fixed effects are held at their estimates and only random effects are drawn.
  • get_index(), get_cog(), get_eao(), and get_weighted_average() can now take a fitted model and prediction grid directly, e.g., get_index(fit, newdata = grid). These functions and get_index_split() also gain an offset argument.
  • project() gains sample_fe, sample_historical_re, and sample_future_re arguments to separate parameter uncertainty, historical latent state uncertainty, and future process variation, and a future_re argument for including (the default), zeroing, or fixing future spatiotemporal and time-varying effects. Projections are faster when newdata repeats spatial locations across time, and project() now keeps only the simulated values it returns, which more than halves peak memory use with many simulations.
  • sdmTMB_cv(lfo = TRUE) now supports delta/hurdle families.
  • Add opt-in collapse_spatiotemporal_ar1 and collapse_ar1_threshold controls to simplify spatiotemporal AR1 fields to IID or random-walk fields when the estimated correlation is near zero or one.
  • Covariate diffusion handles non-local covariates better: time-indexed formulas are distinguished, external grids are supported for prediction and cross-validation, and insufficient grid coverage gives clear errors.
  • Covariate diffusion's kappaS_nl now starts at a value scaled to the data's spatial extent and log_kappaS_nl is bounded by default, which avoids degenerate over-smoothed fits. Override the bounds with lower or upper in sdmTMBcontrol().

Bug fixes: statistical and likelihood

  • Fixed wrong gradients for censored_poisson() (and other censored count families) when censored_upper had non-integer values. Bounds are now rounded down, as documented, when the model is set up.
  • Simulating new correlated random intercepts and slopes, e.g., (1 + x | g), with simulate(re_form = ~0) on the TMB backend no longer gives an error.
  • Rows with missing values in the response or any variable the model uses (including weights and offset) are now omitted before fitting, as with na.omit in glm(), with a message unless silent = TRUE. Previously, such rows were not removed from the spatial, temporal, random-effect, and spatially varying inputs, so later rows were matched to the wrong locations and times and fits were silently incorrect. predict(), residuals(), and sdmTMB_cv() now work for these fits, and the fitted object's data holds the rows used.
  • sdmTMB_simulate() now errors if sigma_E has more than one value, which previously silently simulated a constant SD.
  • truncated_nbinom1() and truncated_nbinom2() now error on a response of zero in non-delta models instead of reporting convergence with an infinite objective.
  • Fix three bugs in priors. normal() priors on b used the standard deviations as variances; a single b prior with multiple coefficients was silently dropped and is now applied to every coefficient; and with bayesian = TRUE the Jacobian for pc_matern() priors was incorrect.
  • Fix several other statistical bugs in both backends:
  • ordbeta() cutpoints are now constrained to be ordered.
  • gengamma() returns a NaN likelihood where its mean does not exist.
  • A matern_st pc_matern() prior with a shared range no longer drops its range term when there is no matern_s prior.
  • With bayesian = TRUE, the threshold_logistic_s95 prior includes its Jacobian adjustment.
  • Response means without observation error (e.g., simulate(observation_error = FALSE)) are now expectations for the beta-binomial, truncated negative binomial, mixture, and ordered beta families.
  • get_eao() weights density by area.
  • sigma_V priors are no longer applied twice in delta models.
  • Fix censored_poisson() likelihoods and gradients, which since sdmTMB 0.4.0 evaluated the censored CDF terms at the starting values. Log likelihoods are also now computed on the log scale, avoiding -Inf for observations far in the tails.
  • Fix time_varying models with more than one column (e.g., ~ 1 + x), where estimated b_rw_t and sigma_V for all but the last term were shrunk. Fitted values and predictions are unchanged, but the log likelihood (and therefore AIC) shifts relative to earlier versions, so don't compare these across versions.
  • Fix covariate diffusion with diffusion() but no time_lag() in nonlocal_formula. The time column of the nonlocal grid was ignored, so the diffused covariate was zero in every time slice after the first and the fit was silently wrong.
  • Fix student(link = "inverse"), which errored ("illegal family argument") while computing starting values.
  • Fix breakpt() likelihoods and gradients after the cutpoint moves from its starting value in the TMB backend.
  • Fix ordbeta() simulation, which understated ones and the mean. The likelihood was unaffected.
  • Fix TMB-backend simulation of AR1 and RW spatiotemporal fields with a barrier mesh, which had the wrong variance.
  • Fix deviance and deviance residuals: they now include observation weights, binomial residuals work for responses with more than one trial, nbinom1() uses the saturated model with phi fixed, and Poisson-link delta encounter residuals are negative for zeros.
  • Fix sdmTMB_cv(lfo = TRUE) log likelihoods for lognormal models, which omitted a logarithm.
  • Mixture-family predictions now respect non-log links and population-level predictions (re_form = NA).
  • Fix delta models with spatial_varying where a component has spatial = "off" (e.g., spatial = list("on", "off")). That component's spatially varying coefficient fields entered the model without a random field penalty and with an unidentified SD parameter. They now have a random field density and their own estimated range.

Bug fixes: prediction, indices, and other

  • simulate() with newdata now uses the covariate-diffusion field built from newdata (or nonlocal_newdata) rather than the fitted one.
  • Response-scale predict() draws (nsim or mcmc_samples) now use each draw's ordered-beta cutpoints and truncated-NB dispersion instead of the fitted estimates.
  • compare_deviance() now errors if the models use different likelihood weights or censored_upper bounds.
  • tidy(effects = "ran_vals") for delta models with time_varying coefficients now labels each row with the correct model component. It was returning both components labelled with the requested model. As with IID random effects, both components are returned regardless of model.
  • tidy(effects = "ran_pars") again reports sigma_V, the SD of time-varying coefficients, for all time_varying_type values. It was being silently dropped, and AR1 time-varying models were skipped entirely. With more than one time-varying coefficient, the sigma_V and

The NEWS section is longer than shown here.

From NEWS.md in the release

Install

Health

CRAN checks
13OK
Slowest check: 16.2 min · r-release-macos-x86_64
Status changes
  • OK13 OK2026-10-21
  • NOTE10 OK, 3 NOTE2026-10-17
  • WARNING7 OK, 5 NOTE, 1 WARNING2026-10-01
  • NOTE10 OK, 3 NOTE2026-07-16
  • OK13 OK2026-07-04
Show 12 earlier changesHide 12 earlier changes
  • WARNING12 OK, 1 WARNING2026-07-03
  • OK13 OK2026-06-27
  • ERROR12 OK, 1 ERROR2026-06-24
  • OK13 OK2026-06-19
  • WARNING12 OK, 1 WARNING2026-06-17
  • OK13 OK2026-06-09
  • ERROR12 OK, 1 ERROR2026-06-07
  • OK13 OK2026-05-20
  • ERROR12 OK, 1 ERROR2026-05-17
  • OK13 OK2026-04-28
  • ERROR10 OK, 3 NOTE, 1 ERROR2026-04-24
  • NOTE11 OK, 3 NOTE2026-03-10
Advisories

none known

Documentation

In release 1.2.0
README· In the repository, left out of the releaseVignettesYes · 1 · dynamicNEWSYes · 100% structured · mentions 1.2.0Citation fileYes · cites a publicationWebsiteYes · pkgdown

The repository also keeps web-only articles.

Cites a JSS article
Help pages
48 (2 internal)
Examples that run
86%37 run in a plain check (11 of them under a condition) · 6 only when donttest examples are enabled (R CMD check --as-cran)
Exported functions with examples
95%
Documented parameters
96%
Return-value docs
97%
Help pages citing references
31%

Downloads

65.6K
CRAN downloads in the past year
Rank #1,734 · ~180/day · ~5.5K/mo
Daily download trend is not available in this view yet.
4.7K30 days
12K90 days
65.6K1 year
Compare downloads with other packages →
Also on766 r2u2 autocran43 c2d4u

Repository

256Stars
33Forks
16Open issues
2Open PRs
14Releases
3,167Commits
21Commit identities
rglmmspatial-analysisecologytmbspecies-distribution-modelling
3,167 commits · Last activity 2026-10-19 · 0% stars, 30d · Default branch at 1.2.0.9000, ahead of CRAN 1.2.0 (checked 2026-10-18) · Discussions: 189 posts
Responsiveness
How these are sampled
PRs merged (all time)
80%
Median days to close, 50 most recently updated closed issues
152
Median days to close, 50 most recently updated closed PRs
1

Stars over time

2025-08-23 · 2222026-09-09 · 256
PracticesBeta

11 development-tooling and community-health practices detected across 6 families in the upstream repository

Checks run against github.com/sdmtmb/sdmtmb on 2026-10-18.

Continuous integration (2)
GitHub ActionsR CMD check workflow

The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel

Docs source (4)
README.Rmdpkgdown

GitHub Pages site last deployed 2026-10-17 · The repository has a site deploy workflow

pkgdown site last built 2026-10-17

Coverage (1)
Coverage reporting (Codecov)
Reproducibility and dev environment (2)
data-raw/Makefile
Show all practicesHide 2 practices
CRAN release process (1)
cran-comments.md
Lint, format, editor (1)
RStudio project
How this is detected·Detection ruleset v3 (2026-09-26)
AI coding toolsBeta

This repository shows signs of AI coding tools.

  • Claude Codefirst seen 2025-07-12
    Named in .Rbuildignore: .claude, CLAUDE.md
    Named in .gitignore: .claude, CLAUDE.md
    Pull request it wrote: opened by a project member
    Commits: 2 by its own account · at least 6 crediting it in the message
  • Gemini CLIfirst seen on or before 2026-07-18
    Config: a file or ignore line, not recorded which
Models named in its commits
  • Claude Opus 5.56 commits · Sep to Oct 2026
Counts are commits, not lines of code. Commits by a tool's accounts count once across all of its accounts. Commits crediting it are the largest count among its credit lines, a minimum.How this is detected·Detection ruleset v4 (updated 2026-09-27)

Dependencies

Declared dependencies
39 external dependencies (excludes base and recommended)

Installing sdmTMB adds 39 packages (27 with compiled code, 39 MB of source tarballs). Heaviest: sf 9.3 MB, igraph 4.8 MB, sp 4.3 MB.

Depends (1)
R >= 4.1.0
LinkingTo (2)
Enhances (0)
none
Reverse dependencies
1direct
0indirect
Imports 1
Suggested by 3
Depends, Imports or LinkingTo, most downloaded first
Suggests, most downloaded first

Datasets

People & History

People (23)
Author, Maintainer since 0.2.1 (2023)
Author, Copyright holder
VAST author
Contributor · added in 0.8.0
Contributor, Copyright holder
glmmTMB author
Contributor, Copyright holder
glmmTMB author
Contributor, Copyright holder
SPDE barrier
Contributor, Copyright holder
glmmTMB author
Contributor, Copyright holder
brms: smoother matrix parsing
Contributor
Contributor
Vignette writing
Show 9 more contributorsHide 9 contributors
Contributor, Copyright holder
TMB/glmmTMB author
Contributor, Copyright holder
glmmTMB author
Contributor, Copyright holder
glmmTMB author
Contributor, Copyright holder
VAST contributor
Contributor, Copyright holder
glmmTMB author
Contributor, Copyright holder
glmmTMB author, SPDE barrier
Contributor
Censored Poisson
Contributor, Copyright holder
mgcv: smoother prediction
Contributor, Copyright holder
glmmTMB author
Listed in earlier versions (9)
Show 8 of 9 peopleHide 8 people
Lewis A.
no longer listed · 0.2.1 to 1.2.0
Philina A.
no longer listed · 0.2.1 to 1.2.0
Cole C.
no longer listed · 0.2.1 to 1.2.0
Sean C.
no longer listed · 0.2.1 to 1.2.0
Eric J.
no longer listed · 0.2.1 to 1.2.0
Hans J.
no longer listed · 0.2.1 to 1.2.0
Olav Nikolai
no longer listed · 0.2.1 to 1.2.0
James T.
no longer listed · 0.2.1 to 1.2.0
Releases (16)

Pick two releases to compare their code metrics.

  • 1.2.0Latest
    record
    2026-07-03 · current release · diff ↗ ·
    removed 4 exports
    add_barrier_mesh, delta_poisson_link_gamma, delta_poisson_link_lognormal, extract_mcmc
    added 13 exports
    censored_betabinomial, censored_binomial, censored_nbinom1, censored_nbinom2, compare_deviance, diffusion, get_censored_upper, get_prior_densities, get_prior_parameters, lognormal_prior, make_zero_one_map, ordbeta, time_lag
  • 1.1.0
    record
    2026-07-03 · diff ↗ ·
    added 3 exports
    make_areal_domain, plot_nonlocal_covariate, plot_nonlocal_kernel
  • R
    R 4.6.0 released · 2026-04-24
  • 1.0.0
    record
    2026-01-24 · diff ↗ ·
    added 1 export
    simulate_new
  • 0.8.1
    record
    2026-01-08 · diff ↗
  • 0.8.0
    record
    2025-11-26 · diff ↗ ·
    added 5 exports
    betabinomial, cv_to_waywiser, get_range_edge, get_weighted_average, make_category_svc
  • 0.7.4
    record
    2025-07-29 · diff ↗
  • 0.7.2
    record
    2025-06-19 · diff ↗
  • R
    R 4.5.0 released · 2025-04-11
  • 0.7.0
    record
    2025-04-01 · diff ↗ ·
    added 5 exports
    cAIC, gamma_cv, get_eao, get_index_split, project
  • 0.6.0
    record
    2024-05-30 · diff ↗
  • R
    R 4.4.0 released · 2024-04-24
  • 0.5.0
    record
    2024-04-03 · diff ↗ ·
    added 2 exports
    delta_gengamma, gengamma
  • 0.4.3
    record
    2024-02-29 · diff ↗
  • 0.4.2
    record
    2024-01-18 · diff ↗
  • 0.4.1
    record
    2023-11-03 · diff ↗ ·
    added 1 export
    set_delta_model
Show 7 earlier eventsHide 7 earlier events
  • 0.4.0
    record
    2023-10-20 · diff ↗ ·
    removed 1 export
    inla_installed
    added 1 export
    nbinom2_mix
  • R
    R 4.3.0 released · 2023-04-21
  • unarchivedReturned to CRAN
    2023-01-28
  • 0.3.0
    record
    2023-01-28 · diff ↗ ·
    added 1 export
    replicate_df
  • archivedRemoved from CRAN
    2023-01-25
    issues were not corrected in time
  • 0.2.1
    record
    2023-01-10
  • R
    R 4.2.0 released · 2022-04-22

Package metadata

First published
2023-01-10
Total releases
16 / 3 yrs
License
GPL-3 OSI
Copyright
inst/COPYRIGHTS
Minimum R
≥ 4.1.0
Bundled data
483 KB / 10 files
Download size
1.1 MB

Cite

Cite this package

Run in R for the authors' entry:

citation("sdmTMB")

The package provides a citation file, so citation() returns the authors' own entry.

It points to 10.18637/jss.v115.i02.

Cite the R Observatory

For a number measured here: a download total, a coverage figure, an archival date.

APA

Balamuta, J. J. (2026). R Observatory: Metrics for sdmTMB version 1.2.0 [Data set]. HJJB, LLC. Data release v2026-10-22. https://doi.org/10.5281/zenodo.21843040

From data release v2026-10-22, which the citation names so these numbers can be found later. More on citing and the projects behind them.

Report a problem with this page →

Privacy choices

These apply to this browser and are stored on this device only. Nothing about your choice is sent to us.

Read the privacy policy