Contents
Overview
The dlvm1 (Dynamic Latent Variable Model, lag-1) is a model family for panel data where multiple subjects are measured across multiple time points. It is a multi-level structural equation model that properly decomposes variance into:
- Within-person temporal dynamics: how variables change over time within each individual
- Between-person individual differences: how individuals differ from each other on average
This decomposition yields three network structures:
- Temporal network (within-person): directed lag-1 effects, extracted via
getmatrix(model, "PDC") - Contemporaneous network (within-person): undirected relationships among innovations, extracted via
getmatrix(model, "omega_zeta_within") - Between-person network: undirected relationships among stable individual means, extracted via
getmatrix(model, "omega_zeta_between")
The most common use case is the panel-GVAR model via the panelgvar() wrapper, which models the within-person contemporaneous and between-person structures as Gaussian Graphical Models (GGMs). Panel data requires a minimum of 3 waves (time points).
dlvm1 family is distinct from the var1 family. While var1() / gvar() fit a single VAR model to (possibly pooled) time-series data, the dlvm1 family properly separates within-person and between-person effects in a multi-level framework.
The Panel-GVAR Model
The general dlvm1 model combines a measurement model with lag-1 dynamics at the latent level:
$$\boldsymbol{y}_{it} = \boldsymbol{\nu} + \boldsymbol{\Lambda}\boldsymbol{\eta}_{it} + \boldsymbol{\varepsilon}_{it}$$
Where $\boldsymbol{y}_{it}$ is the observed response vector for person $i$ at time $t$, $\boldsymbol{\Lambda}$ is the factor loading matrix, $\boldsymbol{\eta}_{it}$ is the latent variable vector, and $\boldsymbol{\varepsilon}_{it}$ is the residual vector.
The latent variables are decomposed into within-person and between-person components:
$$\boldsymbol{\eta}_{it} = \boldsymbol{\eta}_{i}^{(B)} + \boldsymbol{\eta}_{it}^{(W)}$$
The within-person component follows a VAR(1) process:
$$\boldsymbol{\eta}_{it}^{(W)} = \boldsymbol{B}\,\boldsymbol{\eta}_{i,t-1}^{(W)} + \boldsymbol{\zeta}_{it}$$
Where $\boldsymbol{B}$ is the temporal network (lag-1 regression coefficients), and $\boldsymbol{\zeta}_{it}$ is the within-person innovation vector with covariance $\boldsymbol{\Sigma}_\zeta^{(W)}$. The between-person component captures stable individual differences: $\boldsymbol{\eta}_{i}^{(B)} = \boldsymbol{\zeta}_{i}^{(B)}$ with covariance $\boldsymbol{\Sigma}_\zeta^{(B)}$.
The general DLVM1 model has five key parameter matrices:
- $\boldsymbol{B}$ (
beta): temporal effects, standardized as PDC (Partial Directed Correlations) - $\boldsymbol{\Sigma}_\zeta^{(W)}$ (
sigma_zeta_within): within-person contemporaneous covariance (innovation covariance), or when parameterized as GGM: $\boldsymbol{\Omega}_\zeta^{(W)}$ (omega_zeta_within) - $\boldsymbol{\Sigma}_\zeta^{(B)}$ (
sigma_zeta_between): between-person covariance (individual differences), or when parameterized as GGM: $\boldsymbol{\Omega}_\zeta^{(B)}$ (omega_zeta_between) - $\boldsymbol{\Sigma}_\varepsilon^{(W)}$ (
sigma_epsilon_within): within-person residual covariance - $\boldsymbol{\Sigma}_\varepsilon^{(B)}$ (
sigma_epsilon_between): between-person residual covariance
For the panel-GVAR (the most common special case), $\boldsymbol{\Lambda} = \boldsymbol{I}$ (identity matrix), so observed variables equal latent variables, and both residual covariance matrices are fixed to zero. The within-person contemporaneous and between-person covariance structures are parameterized as GGMs, yielding three network matrices: PDC, omega_zeta_within, and omega_zeta_between.
getmatrix(model, "beta") directly in qgraph(). The PDC matrix is the transpose of beta after standardization. Always use getmatrix(model, "PDC") for visualization.
Within-Person vs Between-Person Decomposition
The decomposition into within-person and between-person effects is the central feature of the DLVM1 framework:
- Within-person effects capture how an individual's variables change relative to their own baseline. The temporal network shows how deviations from a person's mean at one time point predict deviations at the next time point. The within-person contemporaneous network captures partial correlations among same-time-point innovations after accounting for temporal effects.
- Between-person effects capture stable individual differences — how people who score higher on one variable on average also tend to score higher (or lower) on another variable on average. This is modeled as a separate network structure.
This separation is important because within-person and between-person relationships can be quite different. For example, at the between-person level, people who exercise more might also report more stress (because busy people do both), while at the within-person level, exercising on a given day might reduce stress relative to that person's baseline.
Covariance Structures
The DLVM1 model has four covariance components, each of which can be parameterized in four ways:
| Type | Key Matrix | Equation |
|---|---|---|
"cov" |
sigma_zeta_* |
$\boldsymbol{\Sigma}_\zeta$ (directly estimated) |
"chol" |
lowertri_zeta_* |
$\boldsymbol{\Sigma}_\zeta = \boldsymbol{L}_\zeta\boldsymbol{L}_\zeta'$ |
"prec" |
kappa_zeta_* |
$\boldsymbol{\Sigma}_\zeta = \boldsymbol{K}_\zeta^{-1}$ |
"ggm" |
omega_zeta_*, delta_zeta_* |
$\boldsymbol{\Sigma}_\zeta = \boldsymbol{\Delta}_\zeta(\boldsymbol{I} - \boldsymbol{\Omega}_\zeta)^{-1}\boldsymbol{\Delta}_\zeta$ |
These parameterizations can be applied to each of the four model components via separate arguments:
| Argument | Component | panelgvar() default |
|---|---|---|
within_latent |
Contemporaneous within-person (innovation covariance) | "ggm" |
within_residual |
Residual within-person | fixed to zero |
between_latent |
Between-person individual differences | "ggm" |
between_residual |
Residual between-person | fixed to zero |
Wrapper Functions
Several convenience wrappers simplify common use cases of the general dlvm1() function:
| Function | $\boldsymbol{\Lambda}$ | Residuals | Default structure | Use case |
|---|---|---|---|---|
panelgvar() |
$\boldsymbol{I}$ | 0 | "ggm" |
Panel graphical VAR (most common for network analysis) |
panelvar() |
$\boldsymbol{I}$ | 0 | "cov" |
Panel VAR with covariance structures |
dlvm1() |
custom | estimated | flexible | Full model with latent variables (requires lambda) |
panellvgvar() |
custom | estimated | "ggm" |
Latent variable graphical VAR |
ml_gvar() is deprecated. Use panelgvar() or dlvm1() instead.
Data Format
The DLVM1 family accepts two data formats, auto-detected from the type of the vars argument:
Wide Format
In wide format, each row in the data is one subject. Columns represent variable×time combinations. You specify a design matrix where rows = variables, columns = time points, and cell entries are column names in the data. The row names of the design matrix become variable labels in the model.
# Example design matrix for 3 variables across 4 time points:
Design <- matrix(c(
"stress_T1", "stress_T2", "stress_T3", "stress_T4",
"fitness_T1", "fitness_T2", "fitness_T3", "fitness_T4",
"prod_T1", "prod_T2", "prod_T3", "prod_T4"
), nrow = 3, byrow = TRUE)
rownames(Design) <- c("stress", "fitness", "productivity")
# Fit panel graphical VAR:
mod <- panelgvar(data, vars = Design, estimator = "FIML")
Long Format
In long format, each row is one observation for one person at one time point. Specify vars as a character vector of variable names, along with idvar (subject ID) and optionally beepvar (time point indicator). The data is automatically reshaped to wide format internally.
# Long-format specification:
mod <- panelgvar(data,
vars = c("stress", "fitness", "productivity"),
idvar = "subject_id",
beepvar = "wave",
estimator = "FIML")
Standardization
Standardizing the data is recommended for numerical stability. Use the standardize argument:
# Standardize variables (recommended):
mod <- panelgvar(data, vars = ..., standardize = "z", ...)
# Or standardize per wave (useful for wide-format data):
mod <- panelgvar(data, vars = ..., standardize = "z_per_wave", ...)
The "z" option standardizes each variable globally, while "z_per_wave" standardizes each variable separately at each time point, which can be useful when means or variances differ across waves.
Example: Panel GVAR (Wide Format)
This example demonstrates the full panel-GVAR workflow using wide-format data. The data contains multiple subjects measured on several variables across multiple time points.
library("psychonetrics")
library("dplyr")
library("qgraph")
# Load data and design matrix:
# data: wide-format panel data (rows = subjects, columns = variable_time)
# design: matrix mapping variables (rows) to time points (columns)
# Fit saturated panel graphical VAR:
mod <- panelgvar(data, vars = design, estimator = "FIML")
mod <- mod %>% runmodel
# Inspect fit:
mod %>% fit
# Confidence interval plots:
CIplot(mod, "beta")
CIplot(mod, "omega_zeta_within")
CIplot(mod, "omega_zeta_between")
# Model search:
mod <- mod %>%
prune(alpha = 0.01) %>%
stepup(alpha = 0.05)
# Extract the three networks:
temporal <- getmatrix(mod, "PDC")
contemporaneous <- getmatrix(mod, "omega_zeta_within")
between <- getmatrix(mod, "omega_zeta_between")
# Visualize side by side:
Layout <- averageLayout(temporal, contemporaneous, between)
layout(t(1:3))
qgraph(temporal, layout = Layout, theme = "colorblind", cut = 0,
directed = TRUE, diag = TRUE,
title = "Temporal (within)", vsize = 12, mar = rep(5, 4),
asize = 7)
qgraph(contemporaneous, layout = Layout, theme = "colorblind", cut = 0,
title = "Contemporaneous (within)", vsize = 12, mar = rep(5, 4))
qgraph(between, layout = Layout, theme = "colorblind", cut = 0,
title = "Between-person", vsize = 12, mar = rep(5, 4))
Example: Panel VAR on Smoking Data
This minimal example uses a covariance matrix from smoking behavior measured across three waves of the LISS panel study (2008–2010), demonstrating the wide-format specification with summary statistics.
library("psychonetrics")
library("dplyr")
# Covariance matrix from LISS panel (smoking across 3 waves):
smoke <- structure(c(47.2361758611759, 43.5366809116809, 41.0057465682466,
43.5366809116809, 57.9789886039886, 47.6992521367521,
41.0057465682466, 47.6992521367521, 53.0669434731935),
.Dim = c(3L, 3L),
.Dimnames = list(
c("smoke2008", "smoke2009", "smoke2010"),
c("smoke2008", "smoke2009", "smoke2010")))
# Design matrix (1 variable measured at 3 time points):
design <- matrix(rownames(smoke), 1, 3)
# Fit panel VAR model:
mod <- panelvar(vars = design, covs = smoke, nobs = 352)
mod <- mod %>% runmodel
# Evaluate fit:
mod %>% fit
mod %>% parameters
Relationship to Other Approaches
vs var1 / gvar (Single-Subject Models)
The var1 family fits a single VAR model to time-series data from one subject (or pooled across subjects). When using var1() with idvar, subject data is simply concatenated — no between-person effects are estimated. The dlvm1 family properly separates within-person and between-person variance in a multi-level framework.
vs mlVAR
The mlVAR package estimates multi-level VAR models with random effects, yielding person-specific networks. The panel-GVAR instead estimates fixed-effect networks with random intercepts (means). Key differences:
mlVARuses within-person centering with sample means, which can introduce bias (Nickell bias in the temporal network; biased between-person correlations). The panel-GVAR avoids this by using a full multivariate SEM framework.mlVARrequires a large number of repeated measures per person (typically at least 20 time points) for the random effects to be identifiable, and is better suited for data with many subjects and many time points per subject.- The panel-GVAR is better suited for data with limited repeated measures (e.g., 3–10 waves), where random effects are not identifiable. However, because the DLVM1 model scales in complexity with time × variables, it becomes computationally hard with more than roughly 10 waves.
vs RI-CLPM (Random-Intercept Cross-Lagged Panel Model)
The panel-GVAR is closely related to the random-intercept cross-lagged panel model (RI-CLPM). Key differences: the panel-GVAR treats the first wave as endogenous (part of the stationary process, not as an exogenous starting point), constrains parameters to be equal over time (stationarity), and models the within-person contemporaneous and between-person structures as GGM networks (which is generally more parsimonious).
Summary
The dlvm1 family provides multi-level dynamic models for panel data in psychonetrics. Key takeaways:
- The panel-GVAR decomposes panel data into temporal (directed, within-person), contemporaneous (undirected, within-person), and between-person (undirected) network structures
- The
panelgvar()wrapper is the most common entry point for network analysis on panel data - Data requires a minimum of 3 waves (time points) and multiple subjects
- Use
getmatrix(model, "PDC"),"omega_zeta_within", and"omega_zeta_between"to extract the three networks - The same workflow applies:
runmodel→prune→stepup→compare - For single-subject time-series data, see the Var1 Family page instead
Troubleshooting
- Convergence issues: Standardize the data using
standardize = "z"orstandardize = "z_per_wave" - Between-person estimation problems: Try
between_latent = "chol"(Cholesky decomposition) instead of the default GGM parameterization. See Freichel & Epskamp for details. - Poor model fit: May indicate a violation of the stationarity assumption. Consider whether within-person dynamics are stable over time.
Further Reading
- Epskamp, S. (2020). Psychometric network models from time-series and panel data. Psychometrika, 85(1), 206–231. DOI: 10.1007/s11336-020-09697-3