Builds tidy, stacked tables from one or more fitted TAM models. For each model it collects:
observation diagnostics from the model's
$obs_predcomponent (falling back totidy_obs_pred()when absent),population summaries from
$pop(falling back totidy_pop()when absent), andparameter summaries from
$fixed_par/$random_par(falling back totidy_par()when absent),
then stacks per component across models (e.g., all "catch" tables together; all "N"
tables together; all fixed parameters together; each random-effect block together).
Usage
tidy_tam(
...,
model_list = NULL,
interval = 0.95,
label = "model",
label_type = "auto",
process_residuals = TRUE,
process_seed = 123456L
)Arguments
- ...
One or more fitted TAM objects (as returned by
fit_tam()). Supply these ormodel_list, not both.- model_list
A named list of fitted TAM objects. Required to be named; the names are used as label values.
- interval
Confidence level passed to
tidy_pop()andtidy_par()for interval construction. Default0.95.- label
Character scalar giving the label column name to add when stacking across multiple/named models. Default
"model".- label_type
Controls how the label column is coerced. One of:
"auto"(default): numeric when possible, else character."numeric": force numeric conversion (withNAfor non-numeric)."character": keep as character."factor": convert to factor.
- process_residuals
Calculate joint-sample process diagnostics? Use
FALSEfor lightweight consumers that need only existing fitted summaries.- process_seed
Non-negative integer seed for a reproducible local Gaussian joint sample. Default
123456L; the caller's RNG state is restored.
Value
A named list of stacked tables, with formula_effects when present:
obs_pred — a named list of stacked data frames (e.g.,
catch,index);pop — a named list of stacked data frames (e.g.,
ssb,N,M,mu_M,F,mu_F,Z, …);deviations — signed N/F/M process tables, using annual increments for RW processes and mean deviations for IID/AR1. M rows represent unique state blocks. These point estimates exclude unpenalized RW boundary rows.
process_residuals — standardized joint-sample
recruitment,N,FandMtables when available.estcontains the diagnostic draw andfittedthe standardized innovation at the fitted mode. Astatustable records each model's calculation status, explanation, seed and method. Disabled processes, projections and unpenalized boundaries have no rows. M coordinates represent unique state blocks, withstate_blockgiving their order. Missing or invalid joint precision produces a warning and an unavailable status, retaining fitted deviations without fabricating draws.patterns — population and mortality age-year tables for
plot_matrix(). Compatible units follow the first fitted model's displayed metric units, including explicit reference conversions. Unspecified fitted units remain unspecified; reference tables with unknown units remain missing;recruitment — predictions, residuals and optional stock-recruit curves; see
tidy_recruitment();fixed_par — a single stacked data frame of fixed-effect parameters with columns like
par,est,se,lwr,upr, plus indices (e.g.,coef,year,age) and the label column when applicable;random_par — a named list of stacked data frames, one per random-effect block, each with the same schema as
fixed_parplus block-appropriate indices.formula_effects — signed Gaussian q, F/M mean and log observation-SD effect levels, RW increments and numeric-by contributions, grouped by term. Intervals use their joint fitted uncertainty; the zero RW anchor is explicitly marked as fixed.
smoothscontains complete centered smooth functions, including their unpenalized directions, with joint uncertainty on the log F/q-link scale. Log-q and logit-q functions are kept in separate entries. Basis coefficient tables identify basis indices, which are not biological ages or years.
Details
Inputs: Pass models through ... or via model_list =.
Precomputed assessment reference objects of class tam_ref are also accepted. Their
existing tables and uncertainty are retained without constructing a tinyAM
optimizer. A tam_ref may contain a named comparison_scales vector;
those factors are applied to the matching tinyAM population estimates and
uncertainty so the combined tables use the reference's units.
If
...supplies one model, no label column is added.If
...supplies >1 model, a label column is added using the object/expression names from....If
model_listis used, it must be a named list; its names are always used as labels (even when length 1).
Names (from ... or model_list) are passed through utils::type.convert() with as.is = TRUE,
so numeric-like labels (e.g. "2010", "2011") become numeric.
Components present in any model are stacked; columns missing from particular models are filled with
NA values so diagnostics like one-step-ahead residuals survive stacking. Parameter summaries are
stacked separately for fixed and random effects: fixed effects in a single data frame; random
effects as a named list of data frames (one per random-effect block, e.g. "log_f", "log_r",
…).
Process diagnostics
Innovations are whitened using the fitted IID, RW, age-correlated RW or
separable AR1 distribution, including stationary boundaries and age-specific
SDs. All predictions are recomputed through the fitted population code.
One Gaussian parameter perturbation from the stored joint precision is
propagated through the automatic-differentiation Jacobian of those
innovations. This SAM-style local Gaussian approximation retains covariance
across components without constructing a dense residual covariance matrix.
Results for a model do not depend on which other models are supplied or their
order. See plot_process_deviations() and plot_process_residuals() for
reusable viewers of the same tables.
Examples
fit <- fit_tam(
cod_obs,
years = 1983:2024,
ages = 2:14,
N_settings = list(process = "iid", init = "exp"),
F_settings = list(process = "rw", mu_form = NULL),
M_settings = list(process = "off", mu_supplied = ~ I(0.3)),
catch_settings = list(sd_form = ~ 1),
index_settings = list(sd_form = ~ 1, q_form = ~ q_block),
silent = TRUE
)
# Single model: no label column added
fit1 <- fit
tabs1 <- tidy_tam(fit1)
names(tabs1)
#> [1] "obs_pred" "osa" "pop"
#> [4] "patterns" "fixed_par" "random_par"
#> [7] "recruitment" "deviations" "process_residuals"
head(tabs1$fixed_par)
#> par coef year age unit est lwr
#> 1 r0 <NA> 1983 2 thousand fish 4.859111e+05 3.909536e+05
#> 2 sd_r <NA> NA NA <NA> 4.972649e-01 3.668274e-01
#> 3 sd_f <NA> NA NA <NA> 4.932985e-01 4.298799e-01
#> 4 sd_n <NA> NA NA <NA> 5.951395e-01 5.306665e-01
#> 5 sd_catch (Intercept) NA NA <NA> 3.814101e-01 3.007537e-01
#> 6 sd_index (Intercept) NA NA <NA> 4.282125e-01 3.722307e-01
#> upr se se_scale is_proj
#> 1 6.039325e+05 0.11093916 log FALSE
#> 2 6.740836e-01 0.15522297 log NA
#> 3 5.660731e-01 0.07020984 log NA
#> 4 6.674457e-01 0.05850218 log NA
#> 5 4.836969e-01 0.12121827 log NA
#> 6 4.926138e-01 0.07148390 log NA
# Two models via ...: label uses object names
fit2 <- update(fit1, years = 1983:2023)
tabs2 <- tidy_tam(fit1, fit2)
head(tabs2$obs_pred$catch) # contains column "model"
#> model year age obs unit F_y_block F_a_block is_proj pred
#> 1 fit1 1983 2 18 thousand fish 1954-1991 2-3 FALSE 13.281992
#> 2 fit1 1984 2 3 thousand fish 1954-1991 2-3 FALSE 4.438363
#> 3 fit1 1985 2 0 thousand fish 1954-1991 2-3 FALSE 2.539587
#> 4 fit1 1986 2 1 thousand fish 1954-1991 2-3 FALSE 2.211582
#> 5 fit1 1987 2 42 thousand fish 1954-1991 2-3 FALSE 18.146481
#> 6 fit1 1988 2 25 thousand fish 1954-1991 2-3 FALSE 21.066685
#> sd std_res
#> 1 0.3814101 0.7969445
#> 2 0.3814101 -1.0269088
#> 3 0.3814101 NA
#> 4 0.3814101 -2.0809837
#> 5 0.3814101 2.2002381
#> 6 0.3814101 0.4488161
head(tabs2$fixed_par) # fixed effects stacked with "model"
#> model par coef year age unit est lwr
#> 1 fit1 r0 <NA> 1983 2 thousand fish 4.859111e+05 3.909536e+05
#> 2 fit1 sd_r <NA> NA NA <NA> 4.972649e-01 3.668274e-01
#> 3 fit1 sd_f <NA> NA NA <NA> 4.932985e-01 4.298799e-01
#> 4 fit1 sd_n <NA> NA NA <NA> 5.951395e-01 5.306665e-01
#> 5 fit1 sd_catch (Intercept) NA NA <NA> 3.814101e-01 3.007537e-01
#> 6 fit1 sd_index (Intercept) NA NA <NA> 4.282125e-01 3.722307e-01
#> upr se se_scale is_proj
#> 1 6.039325e+05 0.11093916 log FALSE
#> 2 6.740836e-01 0.15522297 log NA
#> 3 5.660731e-01 0.07020984 log NA
#> 4 6.674457e-01 0.05850218 log NA
#> 5 4.836969e-01 0.12121827 log NA
#> 6 4.926138e-01 0.07148390 log NA
names(tabs2$random_par) # e.g. "log_f", "log_r", ...
#> [1] "log_f" "log_r" "log_n"
head(tabs2$random_par$log_f) # random block stacked with "model"
#> model par year age unit est lwr upr se
#> 1 fit1 f 1983 2 <NA> 3.163951e-05 1.619098e-05 6.182817e-05 0.3418188
#> 2 fit1 f 1984 2 <NA> 1.902865e-05 9.263852e-06 3.908629e-05 0.3672649
#> 3 fit1 f 1985 2 <NA> 2.203581e-05 8.746427e-06 5.551718e-05 0.4714493
#> 4 fit1 f 1986 2 <NA> 2.551802e-05 1.171828e-05 5.556869e-05 0.3970659
#> 5 fit1 f 1987 2 <NA> 1.114730e-04 5.373377e-05 2.312556e-04 0.3723237
#> 6 fit1 f 1988 2 <NA> 1.196298e-04 5.844459e-05 2.448693e-04 0.3654775
#> se_scale is_proj
#> 1 log FALSE
#> 2 log FALSE
#> 3 log FALSE
#> 4 log FALSE
#> 5 log FALSE
#> 6 log FALSE
# Named list: must be named; names used as labels (even length 1)
fits <- list(`2023` = fit2, `2024` = fit1)
tabs3 <- tidy_tam(model_list = fits, label = "retro_year")
head(tabs3$pop$N) # column "retro_year" has 2023/2024
#> retro_year year age est is_proj unit
#> 1 2023 1983 2 488245.84 FALSE thousand fish
#> 2 2023 1984 2 265588.98 FALSE thousand fish
#> 3 2023 1985 2 130309.17 FALSE thousand fish
#> 4 2023 1986 2 97455.09 FALSE thousand fish
#> 5 2023 1987 2 187506.91 FALSE thousand fish
#> 6 2023 1988 2 201021.13 FALSE thousand fish