Equations via symbolizer
Source:vignettes/equations-via-symbolizer.Rmd
equations-via-symbolizer.RmddrmSEM produces a graph of distributional
models: each endogenous node is one drmTMB fit,
and paths into mu / sigma / nu /
zi / hu / rho12 are first-class.
Reporting that kind of model in a paper requires writing the per-node
equations, families, links, and assumptions — error-prone work that also
goes stale when the code changes.
symbolizer
renders the equations from the fitted object itself.
Its drmTMB extractor covers exactly the families and
components drmSEM uses, so wiring it up is a thin bridge:
walk the SEM in topological order, symbolize each node’s
drmTMB fit, and collate.
A two-node example
sem <- drm_sem(
size = drm_node(drmTMB::bf(size ~ temp + habitat, sigma ~ temp),
family = stats::gaussian()),
abundance = drm_node(drmTMB::bf(abundance ~ size + temp, zi ~ habitat),
family = drmTMB::nbinom2()),
data = dat
)
#> ℹ Fitting node "size"
#> ✔ Fitting node "abundance" [121ms]
#>
#> ℹ Fitting node "abundance"
#> ✔ Fitting node "abundance" [93ms]
#> Render
sym <- symbolizer::symbolize(sem) # walks sem$records, symbolizes each node
sym # prints a summary header
#> <symbolized_drm_sem: 2 nodes, 6 edges>
#> Nodes (topological order): "size" and "abundance"
#> Use `symbolizer::as_latex()` / `symbolizer::equations()` /
#> `symbolizer::assumption_table()` to render.
symbolizer::as_latex(sym) # publication-quality equations, node-by-node
#> [1] "%% Node: size\n\\begin{aligned}\n\\mathrm{size}_i \\mid \\mu_i,\\, \\sigma_i & \\sim \\mathrm{Normal}(\\mu_i,\\, \\sigma_i^2) \\\\\n\\mu_i & = \\beta_{0} + \\beta_{1} \\, \\mathrm{temp}_i + \\beta_{2} \\, [habitat = \\mathrm{B}] \\\\\n\\log(\\sigma_i) & = \\gamma_{0} + \\gamma_{1} \\, \\mathrm{temp}_i\n\\end{aligned}\n\n%% Node: abundance\n\\begin{aligned}\n\\mathrm{abundance}_i \\mid \\mu_i,\\, \\sigma_i & \\sim \\mathrm{NegBin}(\\mu_i,\\, \\mathrm{size} = \\exp(\\sigma_i)); \\mathrm{Var}(\\mathrm{abundance}_i) = \\mu_i + \\mu_i^2 / \\exp(\\sigma_i) \\\\\n\\log(\\mu_i) & = \\beta_{0} + \\beta_{1} \\, \\mathrm{size}_i + \\beta_{2} \\, \\mathrm{temp}_i \\\\\n\\mathrm{logit}(\\pi_{\\mathrm{zi},\\, i}) & = \\alpha_{0} + \\alpha_{1} \\, [habitat = \\mathrm{B}]\n\\end{aligned}"
symbolizer::equations(sym) # tidy tibble: one row per component, keyed by node
symbolizer::assumption_table(sym) # families, links, deferred components| assumption | expression | biological meaning | status |
|---|---|---|---|
| conditional_distribution | size varies normally around its expected value | explicit | |
| linear_predictor | Expected size is a linear combination of the mean-model predictors | explicit | |
| linear_predictor | Log residual SD of size is a linear combination of the scale-model predictors | explicit | |
| independence | Observations are conditionally independent given the predictors | follows from the formula | |
| positivity | Residual SD is constrained positive via the log link | follows from the formula | |
| no_missing_at_random | — | Observations are assumed not missing in a way that depends on the unobserved response | your responsibility |
| conditional_distribution | abundance is a non-negative count with overdispersion; mean = mu_i; Var(abundance) = mu_i + mu_i^2 / exp(sigma_i) | explicit | |
| non_negative_integer_response | (_i) = _0 + _k k X{ki}$ | log link on mu; mu_i is the expected count of abundance; a unit change in a predictor multiplies the expected count by exp(beta) | explicit |
| linear_predictor | sigma_i parameterises overdispersion on the log scale; small exp(sigma_i) (close to zero) means highly overdispersed, very large exp(sigma_i) approaches Poisson | explicit | |
| independence | Observations are conditionally independent given the predictors | follows from the formula | |
| positivity | is unconstrained on the log scale; is the size parameter () | follows from the formula | |
| no_missing_at_random | — | Observations are assumed not missing in a way that depends on the unobserved response | your responsibility |
| zero_inflation_mixture | Mixture of a structural-zero component and the count distribution | explicit | |
| linear_predictor | P(i = 0) = {, i}; P(_i = k _i > 0) = ^{+}(k; _i, (_i))$ | Hurdle structure on nbinom2: logit for zero vs non-zero, then truncated nbinom2 for positives | explicit |
| linear_predictor | $(_{$ | i}) = _0 + _k k V{ki} | logit link on the hurdle probability |
The collator labels each block with
## Node: <name> so the reader can see exactly which
equations belong to which response. sigma and
zi sub-models appear next to their parent mu,
with the link function spelled out — which makes the component-labelled
grammar of drmSEM concrete instead of abstract.
Scope
symbolize.drm_sem() covers the model
specification layer (per-node distributional equations,
families, links, assumptions). The SEM layer — the DAG,
[dsep()], [fisher_c()], and the
simulation-based effect calculus — stays with drmSEM
itself, because the distribution-mediated effect row of
[indirect_effects()] has no closed-form symbolic
representation by construction. Symbolizer correctly stops at the
per-node equations and lets drmSEM do the propagation.
See also
-
vignette("effect-decomposition")— the simulation-based effect calculus that lives on top of these node equations. -
vignette("drmSEM-overview")— the broader workflow. - The
symbolizersite — supported families and components, equation rendering options, and thesymbolized_modelobject.