Bayesian dynamics recipes (ild_brms)

tidyILD authors

2026-04-17

This article gives copy-paste templates for modest dynamics extensions with [ild_brms()]. It is not a substitute for identification work, prior sensitivity, or specialized DSEM software when that is your estimand. See vignette("temporal-dynamics-model-choice", package = "tidyILD") for how these pieces fit the bigger picture.

Prerequisites

Recipe 1: Random slope for a lagged predictor

library(tidyILD)
set.seed(1)
d <- ild_simulate(n_id = 15, n_obs_per = 12, seed = 1)
d$x <- rnorm(nrow(d))
x <- ild_prepare(d, id = "id", time = "time")
x <- ild_lag(x, x, n = 1L, mode = "gap_aware")
tpl <- ild_brms_dynamics_formula("y", "x_lag1", id_var = "id")
tpl$formula
tpl$notes
# Short chains for illustration only:
# fit <- ild_brms(tpl$formula, data = x, iter = 500, chains = 2, refresh = 0)
# ild_tidy(fit)

ild_brms_dynamics_formula() returns a suggested formula (lag | id) + (1|id); adjust priors via [ild_prior_ild()] and check [ild_diagnose()] (R-hat, ESS).

Recipe 2: Bivariate lag sketch (two variables)

Build two lag columns, then include both fixed effects (and optionally random slopes). A full panel VAR requires more structure than this template; this is a minimal associational extension.

x2 <- ild_panel_lag_prepare(x, c("x", "y"), n = c(1L, 1L), mode = "gap_aware")
names(x2$data)
# Example fixed structure only (not run):
# f2 <- y ~ x_lag1 + y_lag1 + (1 | id)
# fit2 <- ild_brms(f2, data = x2$data, iter = 500, chains = 2, refresh = 0)

Recipe 3: Multivariate outcomes with mvbind (sketch)

For two or more outcomes measured on the same occasions, brms can model them jointly with mvbind() so residuals can correlate across outcomes. This is still not a full panel VAR / DSEM: you must choose lags, priors, and residual structure deliberately. When the estimand is a fully specified dynamic system with feedback, dynamite or lavaan DSEM (or similar) is often more appropriate than stacking outcomes in a single brms formula.

# Not run — requires brms; illustration only:
# library(brms)
# f_mv <- bf(mvbind(mood, stress) ~ mood_lag1 + stress_lag1 + (1 | id)) + set_rescor(TRUE)
# fit_mv <- brm(f_mv, data = x2$data, chains = 2, iter = 500, refresh = 0)
# Build mood_lag1 / stress_lag1 with ild_lag() or ild_panel_lag_prepare() first.

For routing when joint multivariate dynamics or high-dimensional predictors matter, see vignette("ild-specialist-backends", package = "tidyILD").

See also