One-step-ahead residuals, also called forecast or quantile residuals
(Thygesen et al. 2017), computed via TMB::oneStepPredict(). Unlike Pearson
residuals they are iid standard normal under a correctly specified model even
when observations are correlated through composition bins or the model holds
random effects, so they support objective goodness-of-fit testing (Trijoulet
et al. 2023; Stewart and Monnahan 2025). The residualization runs inside the
assessment, so it also accounts for correlation induced by the model's own
random effects.
Usage
osa_residuals(
object = NULL,
source = c("ecov", "index", "catch", "comp", "caal"),
method = "oneStepGaussianOffMode",
discrete = NULL,
parallel = TRUE,
seed = 123,
trace = FALSE,
...,
fit = NULL
)Arguments
- object
A fitted
Rceattleobject, fromfit_mod().- source
Observation sources to residualize: any of
"ecov","index","catch","comp","caal","diet"or"all", defaulting to the five non-diet sources. Mirrors thesourceargument ofresiduals.Rceattle(); a source with no observations is skipped silently,"diet"is opt-in because it needs a multispecies model and is expensive, and"ecov"is the state-space covariate, residualized first against its own series as in WHAM'smake_osa_residuals().- method
How the conditional distribution is read: one of
"oneStepGaussianOffMode"(default, the WHAM/SAM choice),"oneStepGaussian","fullGaussian","oneStepGeneric"or"cdf", passed toTMB::oneStepPredict().- discrete
Whether to treat composition observations as the discrete counts they are.
NULL(default) picksTRUEundermethod = "cdf", where the residual is not standard normal without it, andFALSEotherwise.TRUEmakes composition residuals randomized quantile residuals (Dunn and Smyth 1996) and so stochastic – setseed. A Gaussianmethodcannot score a discrete observation, so that group falls back to"oneStepGeneric";"cdf"withdiscrete = FALSEis allowed and says in a message that those residuals are biased up.- parallel
Compute the per-observation loop with
mclapply, defaultTRUE, which is the main speedup for a model with random effects; setoptions(mc.cores = )to choose how many. Where a forked worker aborts instead of returning, the loop recomputes serially and prints the worker's own "irrecoverable exception" message, which comes from C and cannot be suppressed – it does not mean the call failed.- seed
Seed passed to
TMB::oneStepPredict()for reproducible randomized-quantile residuals. Default123.- trace
Print
TMB::oneStepPredict()progress. DefaultFALSE.- ...
Further arguments passed to
TMB::oneStepPredict().- fit
Deprecated name for
object, still accepted; supplying both is an error.
Value
A data frame of class rceattle_osa, one row per residualized
observation, with columns source, fleet, fleet_name, species,
sex, year, age_length_bin, accumulated (the bin folds neighbouring
ages, so it stands for a range rather than the age named), length (the
conditioning length bin for caal, NA otherwise), index_label,
observed, predicted, sd and residual.
observed and predicted are on the residualization scale: log for
lognormal catch and index, natural scale for "Normal" and
"TruncatedNormal", whitened by the lower Cholesky of the survey
covariance for "MVN"/"MVNORM", and bin counts for compositions. Three
cases read differently, and none is an error:
Under
method = "cdf",predictedisNAon every row because the method forms no conditional mode.sdisNAunder the default method too; only"oneStepGaussian"returns one.On a
"TruncatedNormal"fleet under a Gaussian method,predictedis the truncated conditional meanE[x | x > 0], which sits above the fitted index (163.8 against a fitted 100.0 on the package fixture), andsdisNA. The residual is unaffected.A composition
predictedcan go slightly negative where a bin holds almost no fish, and the function warns, naming the count and the years. The bin's own count drives it, not the composition's sample size – median observed count 0.05 on those rows against 4.9 elsewhere – so the warning is not by itself evidence of thin data. Those residuals are biased positive.
Adding a "TruncatedNormal" fleet can move the other fleets' residuals on
a random-effects model, because its rows interleave with the other index
fleets by year instead of forming a contiguous block: a contiguous group
reproduces a single call to 1.5e-14, while an interleaved split moved a
residual by 5.8e-2. Both orderings are valid probability-integral-transform
sequences, so neither is wrong. Fixed-effect models are unaffected.
Attributes carry seed and method – the string that was passed, or a
named vector where a group of rows ran under its own, such as
TruncatedNormal = "oneStepGeneric". Where composition types are present a
"pearson" attribute holds the matching Pearson residuals, on proportions
with the sample size in sample_size rather than the bin counts above, so
the two are not comparable column by column.
Details
Computed post hoc and expensive – TMB re-optimizes the random effects as
each observation is added – so fit_mod() does not produce them, and the fit
must have been optimized at estimateMode < 3. Composition data are
decomposed into univariate conditional residuals (binomial / beta-binomial;
Trijoulet et al. 2023), and the last bin of each composition is fixed by the
sum-to-N constraint, so it has no residual (NA).
Choosing between the methods, what each costs, how they behave under random
effects, the ceiling on |residual| under "cdf", and where compositions at
scale defeat it are in vignette("model-diagnostics"), with the measurements
behind each.
References
Thygesen, U.H., et al. 2017. Validation of ecological state space models using the Laplace approximation. Environ. Ecol. Stat. 24:317-339.
Trijoulet, V., et al. 2023. Model validation for compositional data in stock assessment models. Fish. Res. 257:106487.
Stewart, I.J., and Monnahan, C.C. 2025. Diagnosing common sources of lack of fit to composition data using one-step-ahead residuals. Can. J. Fish. Aquat. Sci. 82:1-13.