Skip to contents

Creates a cross-lagged panel model from a lavaan-like syntax. The syntax (model) can be fairly complicated to read; use the simplify() - function to make it more readable. However, we recommend passing the complex syntax to lavaan instead of the readable one to reduce the likelihood of errors.

Usage

CLPM(
  model,
  data,
  addManifestVar = "variant",
  addLatentVar = "variant",
  meanstructure = FALSE,
  silent = FALSE
)

Arguments

model

string specifying the model

data

longitudinal data in long format. Must have a column named 'person' and a column named 'occasion'

addManifestVar

set to "variant" to add manifest variances which are occasion specific (variant). Set to "invariant" to add manifest variances which are equal for all occasions (measurement invariant). Set to "no" to not add any manifest variances (set to 0)

addLatentVar

set to "variant" to add latent variances which are occasion specific (variant). Set to "invariant" to add latent variances which are equal for all occasions (measurement invariant). Set to "no" to not add any latent variances (set to 0)

meanstructure

set to TRUE to add a mean structure

silent

set to TRUE to suppress messages

Value

list with (1) model -> a string with syntax to pass to lavaan as model, (2) data -> a data set in wide format to pass to lavaan, and (3) internal -> internal objects needed for other functions of lessTemplates.

Examples

# Example 1:
# The following simulation and analysis of a random intercept cross-lagged panel model
# is based on the syntax from Jeroen D. Mulder & Ellen L. Hamaker (2021)
# Three Extensions of the Random Intercept Cross-Lagged Panel Model,
# Structural Equation Modeling: A Multidisciplinary Journal,
# 28:4, 638-648, DOI: 10.1080/10705511.2020.1784738
#
# See https://jeroendmulder.github.io/RI-CLPM/lavaan.html

library(lessTemplates)
library(lavaan)
library(lessSEM)

# Simulate Data
data <- simulateRICLPM()

# Set up model
model <- "
# autoregressive and cross-lagged parameters:
eta1_(u) ~ a11_(u)*eta1_(u-1) + a12_(u)*eta2_(u-1)
eta2_(u) ~ a21_(u)*eta1_(u-1) + a22_(u)*eta2_(u-1)

# covariances
eta1_(u) ~~ 0*eta2_(u) + v11*eta1_(u)
eta2_(u) ~~ v22*eta2_(u)

# Add observations:
eta1_(u) =~ 1*y1_(u)
eta2_(u) =~ 1*y2_(u)

y1_(u) ~~ 0*y1_(u)
y2_(u) ~~ 0*y2_(u)

# random intercepts
RI_eta1 =~ 1*y1_(u)
RI_eta2 =~ 1*y2_(u)

RI_eta1 ~~ vri11*RI_eta1 + vri12*RI_eta2
RI_eta2 ~~ vri22*RI_eta2
"

# create the lavaan syntax using lessTemplates:
m <- lessTemplates::CLPM(model = model,
                               data = data,
                               addManifestVar = "no")
# fit the model:
fit <- sem(model = m$model,
           data = m$data,
           meanstructure = TRUE,
           missing = "ml")
# get the parameter estimates
coef(fit)

## Example 2:
# Simulation of a second order model:
sim <- simulateExample1()

# Let's take a look at the model and the data:
cat(sim$model)
head(sim$data)

# generating the lavaan syntax:
clpm <- CLPM(model = sim$model,
             data = sim$data)

# The syntax generated by CLPM can be quite complicated to read. To simplify
# the syntax, use simplify():
cat(simplify(clpm$model))

# Fit with lavaan:
library(lavaan)
fit <- sem(model = clpm$model,
           data = clpm$data)
coef(fit)[unique(names(coef(fit)))]