---
title: "6. Bayesian VAR and DSEM"
output:
  rmarkdown::html_vignette:
    toc: true
bibliography: references.bib
link-citations: true
vignette: >
  %\VignetteIndexEntry{6. Bayesian VAR and DSEM}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  collapse = TRUE, comment = "#>", message = FALSE, warning = FALSE,
  fig.width = 7, fig.height = 5.5
)
library(idiographic)
data(srl)
has_cograph <- requireNamespace("cograph", quietly = TRUE)
```

`fit_var_bayes()` estimates a single-person Bayesian vector autoregression of
order one: an idiographic model, fitted to one individual's multivariate
series, in which each occasion's measurements are predicted jointly by the
values of all variables one occasion earlier and by the associations that
remain among the variables within the same occasion. The estimands are the
same two within-person networks the ordinary VAR of `fit_var()` returns. The
temporal network is directed: an edge `from -> to` states that the value of
`from` at occasion $t-1$ predicts the value of `to` at occasion $t$, holding
the other lagged variables constant. The contemporaneous network is
undirected: its edges are the partial correlations among the innovations, the
within-occasion associations that lagged prediction does not account for. The
Bayesian estimator places priors on the lagged coefficients and the innovation
covariance and reports posterior distributions over these same quantities, so
each edge carries a credible interval rather than a point estimate alone. The
model presumes weak stationarity — constant mean, variance, and autocovariance
across the observation window — linear lag-one dynamics, approximately
Gaussian fluctuations, and equally spaced measurement occasions.

`fit_mlvar_bayes()` and `fit_mlvar_mplus()` estimate the multilevel analogue,
the Bayesian multilevel VAR in its dynamic structural equation modelling
(DSEM) formulation. Where the single-person
model describes one individual, the multilevel model pools a panel of
individuals and separates the variance into layers: a population-level
average within-person temporal network, a population-level average
within-person contemporaneous network, and a between-person network — a
partial-correlation network over the subject means, describing how people who
are high on one variable on average tend to differ on the others. The between
layer is a structure of stable individual differences, not a within-person
process, and the two need not coincide; treating between-person associations
as if they described anyone's dynamics is the ergodicity error the idiographic
literature warns against. `fit_mlvar_mplus()` targets the
Mplus DSEM backend for laboratories with a licensed Mplus installation that
require its syntax and diagnostics; `fit_mlvar_bayes()` estimates a native
model whose explicitly documented slices are validated against frozen Mplus
outputs without requiring the external dependency.

Bayesian estimation is appropriate when posterior intervals, prior
regularization, or DSEM-style modelling is central to the analysis; when the
goal is a fast point-estimate comparison, `fit_var()` and `fit_mlvar()`
provide that baseline. The native Bayesian chunks below are evaluated during
the build, so every printed result comes from the displayed call. Only the
external Mplus call remains unevaluated because it requires licensed software.

# Data and preprocessing

The estimators expect long format: one row per person-occasion, an id column,
and numeric time-varying indicators ordered within person. The bundled `srl`
data hold self-regulated-learning indicators for 36 students measured over
156 occasions each. The single-person calls fit one student, Grace, on five
indicators; the multilevel calls use the full panel of 36 students on the
same variables. Because the estimators absorb assumption violations silently —
a trend, for instance, inflates the autoregressive diagonal rather than
producing an error — the stationarity screen precedes the fit.

```{r vars-audit}
vars <- c("efficacy", "value", "planning", "monitoring", "effort")
preprocess(srl, vars = vars, id = "name", subject = "Grace")
```

Grace's 156 ordered occasions yield 155 complete current/lagged pairs, and no
series trips a trend, high-autoregression, drift, unit-root, or zero-variance
flag, so the models are specified on the series as they stand.

# Fitting the model

The single-person call takes the data, the variable set, the id column, and
the subject; `n_iter` sets the chain length, `n_chains` the number of chains,
and `seed` fixes the random state for reproducibility.

```{r fit-var-bayes}
var_bayes_fit <- fit_var_bayes(
  srl, vars = vars, id = "name", subject = "Grace",
  n_iter = 1000, n_chains = 2, seed = 1
)
var_bayes_fit
```

The evaluated fit uses two chains, retains 1,000 posterior draws after burn-in,
and reports a maximum potential scale reduction statistic close to 1. No
temporal 95% credible interval excludes zero in this run.

The multilevel Bayesian call uses the same panel structure as `fit_mlvar()`.
Setting `temporal = "fixed"` estimates the average lag-one matrix without
subject-specific random deviations; `n_iter`, `n_chains`, and `seed` control
the MCMC as before.

```{r fit-mlvar-bayes}
mlvar_bayes_fit <- fit_mlvar_bayes(
  srl, vars = vars, id = "name", temporal = "fixed",
  n_iter = 1000, n_chains = 2, seed = 1
)
mlvar_bayes_fit
```

The evaluated multilevel fit also retains 1,000 posterior draws and has a
maximum potential scale reduction statistic close to 1. Three of the 25 temporal
95% credible intervals exclude zero.

The Mplus backend call is shown but not evaluated, because it requires the
suggested `mlVAR` and `MplusAutomation` packages plus a licensed Mplus
installation discoverable by `MplusAutomation::detectMplus()`.

```{r fit-mplus, eval=FALSE}
mplus_fit <- fit_mlvar_mplus(
  srl, vars = vars, id = "name",
  temporal = "fixed", contemporaneous = "fixed"
)
```

# Reading the output

The single-person posterior medians reproduce the ordinary VAR pattern.
Monitoring at occasion $t-1$ predicts lower value at occasion $t$ (posterior
median −0.121), planning predicts higher effort (0.107), and the largest
contemporaneous edge is monitoring–effort (0.465). None of the temporal
credible intervals excludes zero, so these medians are descriptive rather than
evidence of selected temporal paths. The same accessors that serve the point-estimate
fits apply: `summary()` reports one row per network layer, `edges()` lists
edges in decreasing magnitude, `nodes()` gives node-level strength, and
`matrices()` returns the underlying posterior-median matrices.

```{r output-var-bayes}
summary(var_bayes_fit)
edges(var_bayes_fit, n = 12)
nodes(var_bayes_fit)
matrices(var_bayes_fit)
```

The Bayesian mlVAR fit gives a temporal mean absolute weight of 0.015,
a contemporaneous mean absolute weight of 0.165, and a between-person mean
absolute weight of 0.205 in this panel. Monitoring at occasion $t-1$
to effort at occasion $t$ is the largest average temporal edge (posterior
median 0.033). Planning–effort is the largest contemporaneous edge (0.274), and
efficacy–planning is the largest between-person edge (0.548) — a statement about which
students report high efficacy and high planning on average, not about either
process unfolding within any student.

```{r output-mlvar-bayes}
summary(mlvar_bayes_fit)
edges(mlvar_bayes_fit, n = 12)
nodes(mlvar_bayes_fit)
matrices(mlvar_bayes_fit)
```

The `plot()` method draws the layers with the same conventions as the other
estimators: arrows for lag-one prediction in the temporal panel, undirected
edges for the contemporaneous and between layers, width scaled by absolute
weight and colour encoding sign.

```{r plot-var-bayes, eval=has_cograph}
plot(var_bayes_fit)
plot(var_bayes_fit, layer = "temporal")
plot(var_bayes_fit, layer = "contemporaneous")
```

```{r plot-mlvar-bayes, eval=has_cograph}
plot(mlvar_bayes_fit)
plot(mlvar_bayes_fit, layer = "temporal")
plot(mlvar_bayes_fit, layer = "contemporaneous")
plot(mlvar_bayes_fit, layer = "between")
```

The evaluated calls remove the gap between displayed code and reported output,
but they are still examples rather than a universal MCMC prescription. Applied
analyses require problem-specific chain lengths, convergence diagnostics,
posterior predictive checks, and sensitivity analyses over the priors.
`fit_mlvar_mplus()` additionally depends on an external Mplus installation,
so it is demonstrated only as a call template.

# References
