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)
Rolling networks relax the one assumption every full-series model in this package shares: that a single within-person process holds across the whole observation window. A vector autoregression fitted to all of one person's occasions returns one temporal and one contemporaneous network and asserts, through its weak-stationarity assumption, that the same dynamics generated the first week of the protocol and the last. Rolling estimation withdraws that assertion. It slides a window of fixed length along the ordered series of a single person and refits the estimator inside each window, so stationarity is required only locally, within a window, and the sequence of window fits describes how that person's own dynamics change over the protocol.
The estimand is correspondingly local and within-person. A temporal edge
from -> to in a given window states that this person's deviation on from
at occasion $t-1$ predicts their deviation on to at occasion $t$, for the
occasions inside that window, holding the other lagged variables constant. A
contemporaneous edge is a window-local partial correlation among the
within-occasion innovations — the associations that lag-one prediction inside
the window does not account for [@bringmann2013; @epskamp2018mlvar]. Nothing
in either estimand refers to other people: every window is estimated from one
individual's occasions, and differences between windows are within-person
variation in estimated dynamics, not differences between persons.
Two rolling estimators are provided. fit_rolling_var() refits the ordinary
least-squares VAR in each window and is the unregularized, time-varying
baseline: every window returns a dense temporal matrix and a dense
contemporaneous matrix. fit_rolling_graphical_var() refits the penalized
two-step estimator in each window — lasso-penalized lagged
regressions, a graphical lasso on their residuals, the penalty
selected per window by the extended Bayesian information criterion — so each
window carries its own sparsity decision. Both are
descriptive instruments: a sequence of window fits shows that local dynamics
differ, not why they differ. Rolling estimation is also not a remedy for short
series — each window contains fewer observations than the full series, so the
window size sets a bias-variance tradeoff in which smaller windows track
change more finely but estimate every network from less data. Because
adjacent windows share most of their occasions, their estimates are strongly
dependent, and window-size sensitivity should be reported whenever rolling
networks are offered as evidence of changing dynamics.
The rolling estimators expect the same long format as their full-series
counterparts: 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. Passing
subject = "Grace" selects her series inside the call, so the full srl data
remain intact. The stationarity screen precedes the fit.
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. A clean global screen does not settle the question rolling estimation asks: the whole-series diagnostics average over the protocol, and dynamics that shift midway can leave every global flag silent. The window fits below pose that local question directly.
window_size sets the number of occasions in each local fit, step sets how
far the window advances, and keep_fits = TRUE stores each fitted window
model so that matrices() and plot() can inspect a selected window
afterwards. With Grace's 156 occasions, a 50-occasion window advancing by 20
gives six windows, starting at occasions 1, 21, 41, 61, 81, and 101 and
ending at occasion 150; each window's networks are estimated from the 49
lagged pairs its 50 occasions provide.
rolling_ols <- fit_rolling_var( srl, vars = vars, id = "name", subject = "Grace", window_size = 50, step = 20, scale = TRUE, keep_fits = TRUE ) rolling_ols
The ordinary rolling fit returns six windows for Grace, each holding a dense least-squares temporal matrix and a dense contemporaneous matrix — the unregularized, time-varying baseline against which the sparse variant can be read.
The graphical variant repeats the penalized estimation in every window.
Sparse selection contributes sampling variability of its own — the selected
edge set can change from window to window even when the underlying process
does not — so a larger window of 70 occasions advancing by 25 is used to
partially offset it, and a coarse penalty grid (n_lambda = 8) with
gamma = 0, the plain-BIC end of the criterion, keeps the per-window
selection inexpensive and less severe toward retained edges than the default
gamma = 0.5.
rolling_gvar <- fit_rolling_graphical_var( srl, vars = vars, id = "name", subject = "Grace", window_size = 70, step = 25, n_lambda = 8, gamma = 0, keep_fits = TRUE ) rolling_gvar
The graphical rolling fit returns four windows, starting at occasions 1, 26, 51, and 76, each estimated from the 69 lagged pairs its 70 occasions provide and each carrying its own EBIC-selected sparsity decision.
as.data.frame() flattens a rolling result to one row per window and edge,
with the window's start and end rows carried alongside each weight; the first
twelve rows cover the temporal edges of Grace's first window.
head(as.data.frame(rolling_ols), 12)
Within the first window, monitoring at occasion $t-1$ predicts lower efficacy at $t$ (-0.272), planning predicts lower value (-0.265), and planning predicts higher effort (0.277). These local coefficients exceed anything the full-series least-squares fit reports for the same student — its largest temporal coefficient is 0.160 in absolute value — which is the rolling tradeoff stated numerically: a 50-occasion window can express transient local dynamics that the full series averages away, and it estimates them with correspondingly more noise.
matrices(rolling_ols, fit = 1)
matrices() with fit = 1 returns the first window's coefficient matrices:
the lag-one temporal matrix, the residual covariance and precision of the
innovations, and the partial correlations derived from them. The window-one
contemporaneous layer is dominated by efficacy–monitoring (0.447) and
monitoring–effort (0.440), close to Grace's full-series contemporaneous
pattern: in this series the within-occasion structure is more stable than the
temporal coefficients.
edge_counts <- do.call(rbind, lapply(seq_along(rolling_gvar$fits), function(i) { data.frame(window = i, summary(rolling_gvar$fits[[i]])) })) edge_counts edges(rolling_gvar$fits[[1]]) matrices(rolling_gvar, fit = 1)
All four sparse windows retain no temporal edges, matching the full-series graphical fit for the same student. This is an executed selection result, not a missing or disabled network; with these data, windows, and criterion, the regularized temporal layer is empty. The first window's contemporaneous layer keeps efficacy–monitoring (0.247), monitoring–effort (0.264), and a small planning–effort edge (0.071) — the same three within-occasion partial correlations the full-series graphical fit selects, here at window-local magnitudes.
Plotting a rolling fit with fit = 1 draws the selected window's temporal
and contemporaneous panels side by side, with edge width scaled to absolute
weight and colour encoding sign.
plot(rolling_ols, fit = 1)
The first-window OLS plot is dense, as every unregularized window is: each of the 25 possible temporal arrows and 10 possible contemporaneous edges carries some estimate, and the eye is drawn by width rather than by presence.
plot(rolling_ols, fit = 1, layer = "temporal")
The temporal panel isolates the local lag-one structure — the monitoring-to-efficacy and planning-to-effort effects read from the table above.
plot(rolling_ols, fit = 1, layer = "contemporaneous")
The contemporaneous panel carries the efficacy–monitoring–effort core that also anchors Grace's full-series fits.
plot(rolling_gvar, fit = 1, layer = "contemporaneous")
The sparse window keeps the same core and sets the remaining within-occasion
associations to exact zeros. Redrawing this panel for each of the four
windows, by varying fit, is the graphical form of the question rolling
estimation answers: whether this person's local structure holds steady or
moves over the protocol.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.