---
title: "3. Ordinary VAR"
output:
  rmarkdown::html_vignette:
    toc: true
bibliography: references.bib
link-citations: true
vignette: >
  %\VignetteIndexEntry{3. Ordinary VAR}
  %\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
)
```

```{r libraries}
library(idiographic)
data(srl)
vars <- c("efficacy", "value", "planning", "monitoring", "effort")
has_cograph <- requireNamespace("cograph", quietly = TRUE)
```

The first-order vector autoregression, VAR(1), is the reference model for
person-specific network estimation from intensive longitudinal data. It models
one person's multivariate series as a first-order Gaussian process, in which
each occasion's measurements depend jointly on the values of all variables one
occasion earlier and on the associations that remain among the variables
within the same occasion. It is an idiographic model, estimated for a single
individual, on the premise that within-person dynamics need not match the
between-person structure of the group. It presumes weak
stationarity, meaning that the mean, variance, and autocovariance of every
series are constant across the observation window; linear, lag-one dynamics;
approximately Gaussian fluctuations; and equally spaced measurement occasions.

The model yields two networks over the same variables [@epskamp2018mlvar]. The
temporal network is directed within-person lag-one prediction: an edge
`from -> to` states that the value of `from` at occasion $t-1$ predicts the
value of `to` at occasion $t$ within the same person, holding the other lagged
variables constant, which is predictability in the Granger sense
[@bringmann2013]. The self-loop of each variable is its autoregression — the
inertia, or carry-over, of that variable from one occasion to the next. The
contemporaneous network is undirected within-occasion partial correlation:
after the previous occasion has explained what it can, the part of each
variable left unexplained — its innovation — may still be associated with the
innovations of the others, and the contemporaneous edges are the partial
correlations among these remainders, the within-occasion associations that
lagged prediction does not account for.

`fit_var()` estimates both networks by ordinary least squares, one regression
per variable, without regularization. Each equation carries one coefficient
per lagged predictor plus an intercept, so the size of the temporal network
grows quadratically in the number of variables and the sampling variance of
the estimates grows with it. Under a correctly specified linear VAR with
exogenous innovations, the coefficient estimates are unbiased; every cell of both
networks receives a coefficient, and no edge is removed on the estimator's
behalf, which leaves the analyst to judge which small values are noise. This
makes ordinary VAR the transparent unregularized baseline: the appropriate
estimator when the number of occasions is large relative to the number of
parameters and every estimate is wanted for inspection, and the reference
against which the regularized `fit_graphical_var()` trades variance for
sparsity by shrinking weak edges to exactly zero under an extended-BIC penalty.
For several people, `fit_var_each()` fits a
separate ordinary VAR per person and `fit_mlvar()` pools information across
people through random effects.

# Data and preprocessing

The estimator expects 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; this vignette fits a single student, Grace, on five
indicators: `efficacy`, `value`, `planning`, `monitoring`, and `effort`.
`fit_var()` standardizes each variable to unit variance (`scale = TRUE`), so
that coefficients are comparable across indicators, and centres within person
(`center_within = TRUE`), so that the intercept absorbs the person mean; it
does not remove trends. Because a violated assumption is absorbed silently — a
trend, for instance, inflates the autoregressive diagonal rather than
producing an error — the stationarity screen precedes the fit.

```{r audit}
preprocess(srl, vars = vars, id = "name")
```

Across all 36 students the five indicators give 5616 ordered rows, of which
5548 survive as complete current/lagged pairs. Ten subject-series trip the
linear-trend flag and one a drift flag, while the high-autoregression,
unit-root, and zero-variance screens are clear. Grace's own five series are
among the clean ones: her 156 ordered occasions yield 155 complete pairs and
trip no flag, so the model is fitted on her series as they stand. Where a
flagged series is to be modelled, `preprocess(..., detrend = )` constructs and
rechecks the transformed lag design. The same transformation must then be
applied to the long data supplied to `fit_var()`; `preprocess()` does not mutate
the source data. A persistent trend left in place can masquerade as lag-one
structure.

# Fitting the model

The estimator takes the data, the variable set, the id column, and the
subject. The `subject =` argument selects the person inside the call, so the
occasion ordering that the lag-one design requires is preserved rather than
reconstructed by the caller.

```{r fit}
var_fit <- fit_var(srl, vars = vars, id = "name", subject = "Grace",
                   scale = TRUE)
var_fit
```

The call returns a `var_result` object whose print method reports both
estimated networks with their weight ranges and signed-edge counts. Grace
contributes 155 usable occasions, the single lost row being the first
occasion, which has no predecessor. All 25 temporal coefficients and all 10
contemporaneous partial correlations are estimated — least squares retains
every edge — with the temporal weights confined between −0.160 and 0.159 while
the strongest contemporaneous weight reaches 0.467, a first indication that
Grace's within-occasion co-regulation is stronger than her lag-one carry-over.

# Reading the output

The `summary()` method reports one row per network layer, with the edge count,
density, mean absolute weight, and the split of positive and negative edges.

```{r summary}
summary(var_fit)
```

Both layers are fully dense, as they must be under least squares, so the
comparison is carried by the weights: the contemporaneous mean absolute weight
of 0.160 is roughly twice the temporal 0.075. Within-occasion association is
larger than lagged prediction in this fitted series; no claim of typicality is
made from one participant.

The `edges()` accessor returns one row per edge in decreasing magnitude;
`network =` selects a layer and `n =` keeps the strongest edges. For the
temporal layer the `from` and `to` columns read as `from` at occasion $t-1$
predicting `to` at occasion $t$.

```{r edges-temporal}
edges(var_fit, network = "temporal", n = 5)
```

Grace's strongest lag-one coefficients are small. Monitoring on one occasion
predicts lower task value on the next (−0.160), and planning predicts higher
subsequent effort regulation (0.159), conditional on the other lagged
variables. These are predictive associations, not evidence that planning
causes effort or monitoring causes a later change in value. At this magnitude,
and with 155 occasions, the individual temporal coefficients can be
high-variance, so
the temporal layer is better read as a pattern than as a set of point claims.
Where a sparse, multiplicity-controlled temporal network is required,
`fit_graphical_var()` is the estimator of choice.

```{r edges-contemp}
edges(var_fit, network = "contemporaneous", n = 5)
```

The contemporaneous layer is where Grace's process is organized. Monitoring
and effort share a partial correlation of 0.467, and monitoring also couples
with efficacy (0.378) and planning with effort (0.332). Within a single
occasion, monitoring, effort, and efficacy move together after the other
indicators are partialled out; these are the same three edges retained when the
clean-room vignette applies graphical VAR to Grace, there with
shrinkage-biased weights.

Node-level structure follows from `nodes()`, whose strength column sums the
absolute weights incident to each node within a layer, split into out- and
in-strength for the directed temporal network, with the self-loop reported
separately.

```{r nodes}
nodes(var_fit)
```

In the temporal layer `value` has the highest strength (0.832), driven by both
outgoing and incoming effects; in the contemporaneous layer `monitoring` is
the hub (1.003), consistent with its position at the junction of the two
strongest within-occasion edges. The autoregressions are weak throughout — the
largest, for efficacy, is −0.13 — so Grace's states carry little inertia from
one occasion to the next. The full coefficient tables, including intercepts
and self-loops, are available from `coefs(var_fit)`, and the underlying
matrices — the lagged coefficient matrix, the residual covariance, and the
partial-correlation matrix derived from it — from `matrices(var_fit)`.

# Visualizing the network

Plotting the fit draws both layers side by side: arrows in the temporal panel
denote lag-one prediction, edge width scales with absolute weight, and colour
encodes sign.

```{r plot-all, eval=has_cograph}
plot(var_fit)
```

```{r plot-temporal, eval=has_cograph}
plot(var_fit, layer = "temporal")
```

The temporal graph is diffuse, matching the narrow weight range: no single
lagged driver dominates Grace's next-occasion state.

```{r plot-contemp, eval=has_cograph}
plot(var_fit, layer = "contemporaneous")
```

The contemporaneous graph is concentrated: the thick monitoring–effort edge
and its links to efficacy and planning form the within-occasion co-regulation
core that the summary statistics quantified. Because the estimates are
person-specific, both graphs describe Grace's process and carry no claim about
other students.

The two layers together make a mixed network — directed lag-one effects and
undirected contemporaneous partial correlations — and `plot(var_fit, mixed =
TRUE)` draws them in one graph, the temporal edges as curved arrows and the
contemporaneous edges as straight lines.

```{r plot-mixed, eval=has_cograph}
plot(var_fit, mixed = TRUE)
```

# References
