The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Example lavaan models

Rémi Thériault

August 24, 2022

This article attempts to reproduce several different possible lavaan models. We start with the source itself: The lavaan project at https://lavaan.ugent.be. Let’s start by loading both packages.

library(lavaan)
## Warning: package 'lavaan' was built under R version 4.3.1
library(lavaanExtra)

Example 1 (Model syntax 1):

Source: https://lavaan.ugent.be/tutorial/syntax1.html

lavaan:

myModel <- " # regressions
             y1 + y2 ~ f1 + f2 + x1 + x2
                  f1 ~ f2 + f3
                  f2 ~ f3 + x1 + x2

             # latent variable definitions
               f1 =~ y1 + y2 + y3
               f2 =~ y4 + y5 + y6
               f3 =~ y7 + y8 + y9 + y10

             # variances and covariances
               y1 ~~ y1
               y1 ~~ y2
               f1 ~~ f2

             # intercepts
               y1 ~ 1
               f1 ~ 1
           "

lavaanExtra:

reg <- list(
  y1 = c("f1", "f2", "x1", "x2"),
  y2 = c("f1", "f2", "x1", "x2"),
  f1 = c("f2", "f3"),
  f2 = c("f3", "x1", "x2")
)
lat <- list(
  f1 = paste0("y", 1:3),
  f2 = paste0("y", 4:6),
  f3 = paste0("y", 7:10)
)
cov <- list(
  y1 = "y1",
  y1 = "y2",
  f1 = "f2"
)
int <- c("y1", "f1")
myModel <- write_lavaan(
  regression = reg,
  latent = lat,
  covariance = cov,
  intercept = int
)
cat(myModel)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## f1 =~ y1 + y2 + y3
## f2 =~ y4 + y5 + y6
## f3 =~ y7 + y8 + y9 + y10
## 
## ##################################################
## # [---------Regressions (Direct effects)---------]
## 
## y1 ~ f1 + f2 + x1 + x2
## y2 ~ f1 + f2 + x1 + x2
## f1 ~ f2 + f3
## f2 ~ f3 + x1 + x2
## 
## ##################################################
## # [------------------Covariances-----------------]
## 
## y1 ~~ y1
## y1 ~~ y2
## f1 ~~ f2
## 
## ##################################################
## # [------------------Intercepts------------------]
## 
## y1 ~ 1
## f1 ~ 1

Example 2 (A CFA example):

Source: https://lavaan.ugent.be/tutorial/cfa.html

lavaan:

HS.model <- " visual  =~ x1 + x2 + x3
              textual =~ x4 + x5 + x6
              speed   =~ x7 + x8 + x9 "

lavaanExtra:

lat <- list(
  visual = paste0("x", 1:3),
  textual = paste0("x", 4:6),
  speed = paste0("x", 7:9)
)
myModel <- write_lavaan(latent = lat)
cat(myModel)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## visual =~ x1 + x2 + x3
## textual =~ x4 + x5 + x6
## speed =~ x7 + x8 + x9

Example 3 (A SEM example):

Source: https://lavaan.ugent.be/tutorial/sem.html

lavaan:

model <- "
  # measurement model
    ind60 =~ x1 + x2 + x3
    dem60 =~ y1 + y2 + y3 + y4
    dem65 =~ y5 + y6 + y7 + y8
  # regressions
    dem60 ~ ind60
    dem65 ~ ind60 + dem60
  # residual correlations
    y1 ~~ y5
    y2 ~~ y4 + y6
    y3 ~~ y7
    y4 ~~ y8
    y6 ~~ y8
"

lavaanExtra:

lat <- list(
  ind60 = paste0("x", 1:3),
  dem60 = paste0("y", 1:4),
  dem65 = paste0("y", 5:8)
)
reg <- list(
  dem60 = "ind60",
  dem65 = c("ind60", "dem60")
)
cov <- list(
  y1 = "y5",
  y2 = c("y4", "y6"),
  y3 = "y7",
  y4 = "y8",
  y6 = "y8"
)
model <- write_lavaan(
  latent = lat,
  regression = reg,
  covariance = cov
)
cat(model)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## ind60 =~ x1 + x2 + x3
## dem60 =~ y1 + y2 + y3 + y4
## dem65 =~ y5 + y6 + y7 + y8
## 
## ##################################################
## # [---------Regressions (Direct effects)---------]
## 
## dem60 ~ ind60
## dem65 ~ ind60 + dem60
## 
## ##################################################
## # [------------------Covariances-----------------]
## 
## y1 ~~ y5
## y2 ~~ y4 + y6
## y3 ~~ y7
## y4 ~~ y8
## y6 ~~ y8

Example 4 (Model syntax 2):

Source: https://lavaan.ugent.be/tutorial/syntax2.html

Example 4.1

lavaan:

model <- "
# three-factor model
  visual =~ x1 + x2 + x3
  textual =~ x4 + x5 + x6
  speed   =~ NA*x7 + x8 + x9
# orthogonal factors
  visual ~~ 0*speed
  textual ~~ 0*speed
# fix variance of speed factor
  speed ~~ 1*speed
"

lavaanExtra:

lat <- list(
  visual = paste0("x", 1:3),
  textual = paste0("x", 4:6),
  speed = c("NA*x7", "x8", "x9")
)
cov <- list(
  visual = "0*speed",
  textual = "0*speed",
  speed = "1*speed"
)
model <- write_lavaan(latent = lat, covariance = cov)
cat(model)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## visual =~ x1 + x2 + x3
## textual =~ x4 + x5 + x6
## speed =~ NA*x7 + x8 + x9
## 
## ##################################################
## # [------------------Covariances-----------------]
## 
## visual ~~ 0*speed
## textual ~~ 0*speed
## speed ~~ 1*speed

Example 4.2

lavaan:

model <- "
visual  =~ x1 + start(0.8)*x2 + start(1.2)*x3
textual =~ x4 + start(0.5)*x5 + start(1.0)*x6
speed   =~ x7 + start(0.7)*x8 + start(1.8)*x9
"

lavaanExtra:

lat <- list(
  visual = c("x1", "start(0.8)*x2", "start(1.2)*x3"),
  textual = c("x4", "start(0.5)*x5", "start(1.0)*x6"),
  speed = c("x7", "start(0.7)*x8", "start(1.8)*x9")
)
model <- write_lavaan(latent = lat)
cat(model)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## visual =~ x1 + start(0.8)*x2 + start(1.2)*x3
## textual =~ x4 + start(0.5)*x5 + start(1.0)*x6
## speed =~ x7 + start(0.7)*x8 + start(1.8)*x9

Example 4.3

lavaan:

model <- "
f =~ y1 + y2 + myLabel*y3 + start(0.5)*y3 + y4
"

lavaanExtra:

lat <- list(f = c("y1", "y2", "myLabel*y3", "start(0.5)*y3", "y4"))
model <- write_lavaan(latent = lat)
cat(model)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## f =~ y1 + y2 + myLabel*y3 + start(0.5)*y3 + y4

Example 4.4

lavaan:

model <- "
visual  =~ x1 + v2*x2 + v2*x3
textual =~ x4 + x5 + x6
speed   =~ x7 + x8 + x9
"

lavaanExtra:

lat <- list(
  visual = c("x1", "v2*x2", "v2*x3"),
  textual = paste0("x", 4:6),
  speed = paste0("x", 7:9)
)
model <- write_lavaan(latent = lat)
cat(model)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## visual =~ x1 + v2*x2 + v2*x3
## textual =~ x4 + x5 + x6
## speed =~ x7 + x8 + x9

Example 4.5

lavaan:

model <- '
visual  =~ x1 + x2 + equal("visual=~x2")*x3
textual =~ x4 + x5 + x6
speed   =~ x7 + x8 + x9
'
sem(model, data = HolzingerSwineford1939)
## lavaan 0.6.16 ended normally after 36 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        21
##   Number of equality constraints                     1
## 
##   Number of observations                           301
## 
## Model Test User Model:
##                                                       
##   Test statistic                                87.971
##   Degrees of freedom                                25
##   P-value (Chi-square)                           0.000

lavaanExtra:

lat <- list(
  visual = c("x1", "x2", "equal('visual=~x2')*x3"),
  textual = paste0("x", 4:6),
  speed = paste0("x", 7:9)
)
model <- write_lavaan(latent = lat)
cat(model)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## visual =~ x1 + x2 + equal('visual=~x2')*x3
## textual =~ x4 + x5 + x6
## speed =~ x7 + x8 + x9
sem(model, data = HolzingerSwineford1939)
## lavaan 0.6.16 ended normally after 36 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        21
##   Number of equality constraints                     1
## 
##   Number of observations                           301
## 
## Model Test User Model:
##                                                       
##   Test statistic                                87.971
##   Degrees of freedom                                25
##   P-value (Chi-square)                           0.000

Example 4.6

lavaan:

model.constr <- " # model with labeled parameters
                    y ~ b1*x1 + b2*x2 + b3*x3
                  # constraints
                    b1 == (b2 + b3)^2
                    b1 > exp(b2 + b3) "

lavaanExtra:

reg <- list(y = c("b1*x1", "b2*x2", "b3*x3"))
cstr1 <- list(b1 = "(b2 + b3)^2")
cstr2 <- list(b1 = "exp(b2 + b3)")
model <- write_lavaan(
  regression = reg, constraint.equal = cstr1,
  constraint.larger = cstr2
)
cat(model)
## ##################################################
## # [---------Regressions (Direct effects)---------]
## 
## y ~ b1*x1 + b2*x2 + b3*x3
## 
## ##################################################
## # [-----------------Constraints------------------]
## 
## b1 == (b2 + b3)^2
## b1 > exp(b2 + b3)

Example 5 (Mediation)

Source: https://lavaan.ugent.be/tutorial/mediation.html

lavaan:

model <- " # direct effect
             Y ~ c*X
           # mediator
             M ~ a*X
             Y ~ b*M
           # indirect effect (a*b)
             ab := a*b
           # total effect
             total := c + (a*b)
         "

lavaanExtra:

mediation <- list(
  Y = "c*X",
  M = "a*X",
  Y = "b*M"
)
indirect <- list(
  ab = "a*b",
  total = "c + (a*b)"
)
model <- write_lavaan(mediation = mediation, indirect = indirect)
cat(model)
## ##################################################
## # [-----------Mediations (named paths)-----------]
## 
## Y ~ c*X
## M ~ a*X
## Y ~ b*M
## 
## ##################################################
## # [--------Mediations (indirect effects)---------]
## 
## ab := a*b
## total := c + (a*b)

Example 6 (Multilevel SEM)

Source: https://lavaan.ugent.be/tutorial/multilevel.html

lavaan:

model <- "
    level: 1
        fw =~ y1 + y2 + y3
        fw ~ x1 + x2 + x3
    level: 2
        fb =~ y1 + y2 + y3
        fb ~ w1 + w2
"

lavaanExtra:

cus <-
  "level: 1
    fw =~ y1 + y2 + y3
    fw ~ x1 + x2 + x3
level: 2
    fb =~ y1 + y2 + y3
    fb ~ w1 + w2
"
model <- write_lavaan(custom = cus)
cat(model)
## ##################################################
## # [------------Custom Specifications-------------]
## 
## level: 1
##     fw =~ y1 + y2 + y3
##     fw ~ x1 + x2 + x3
## level: 2
##     fb =~ y1 + y2 + y3
##     fb ~ w1 + w2

Example 7 (total effects)

Source: https://methodenlehre.github.io/SGSCLM-R-course/cfa-and-sem-with-lavaan.html#structural-equation-modelling-sem

lavaan:

model_mediation <- "
# Measurement model
SUP_Parents =~ sup_parents_p1 + sup_parents_p2 + sup_parents_p3
SUP_Friends =~ sup_friends_p1 + sup_friends_p2 + sup_friends_p3
SE_Academic =~ se_acad_p1 + se_acad_p2 + se_acad_p3
SE_Social =~ se_social_p1 + se_social_p2 + se_social_p3
LS  =~ ls_p1 + ls_p2 + ls_p3

# Structural model
# Regressions
SE_Academic ~ b1*SUP_Parents + b3*SUP_Friends
SE_Social ~ b2*SUP_Parents + b4*SUP_Friends
LS ~ b5*SUP_Parents + b6*SUP_Friends + b7*SE_Academic + b8*SE_Social

# Residual covariances
SE_Academic ~~ SE_Social

# Indirect effects
b1b7 := b1*b7
b2b8 := b2*b8
totalind_eltern := b1*b7 + b2*b8
b3b7 := b3*b7
b4b8 := b4*b8
totalind_freunde := b3*b7 + b4*b8

# Total effects
total_eltern := b1*b7 + b2*b8 + b5
total_freunde := b3*b7 + b4*b8 + b6
"

lavaanExtra:

x <- c("sup_parents", "sup_friends", "se_acad", "se_social", "ls")
y <- lapply(x, paste0, "_p", 1:3)
y <- setNames(y, x)
lat <- list(
  SUP_Parents = y$sup_parents,
  SUP_Friends = y$sup_friends,
  SE_Academic = y$se_acad,
  SE_Social = y$se_social,
  LS = y$ls
)

b <- paste0("b", 1:8)
d <- c(
  rep(c("SUP_Parents", "SUP_Friends"), each = 2),
  "SUP_Parents", "SUP_Friends", "SE_Academic", "SE_Social"
)
e <- paste0(b, "*", d)

reg <- list(
  SE_Academic = e[c(1, 3)],
  SE_Social = e[c(2, 4)],
  LS = e[c(5:8)]
)

cov <- list(SE_Academic = "SE_Social")

ind <- list(
  b1b7 = "b1*b7",
  b2b8 = "b2*b8",
  totalind_eltern = "b1*b7 + b2*b8",
  b3b7 = "b3*b7",
  b4b8 = "b4*b8",
  totalind_freunde = "b3*b7 + b4*b8",
  total_eltern = "b1*b7 + b2*b8 + b5",
  total_freunde = "b3*b7 + b4*b8 + b6"
)

model <- write_lavaan(
  regression = reg, covariance = cov,
  indirect = ind, latent = lat
)
cat(model)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## SUP_Parents =~ sup_parents_p1 + sup_parents_p2 + sup_parents_p3
## SUP_Friends =~ sup_friends_p1 + sup_friends_p2 + sup_friends_p3
## SE_Academic =~ se_acad_p1 + se_acad_p2 + se_acad_p3
## SE_Social =~ se_social_p1 + se_social_p2 + se_social_p3
## LS =~ ls_p1 + ls_p2 + ls_p3
## 
## ##################################################
## # [---------Regressions (Direct effects)---------]
## 
## SE_Academic ~ b1*SUP_Parents + b3*SUP_Friends
## SE_Social ~ b2*SUP_Parents + b4*SUP_Friends
## LS ~ b5*SUP_Parents + b6*SUP_Friends + b7*SE_Academic + b8*SE_Social
## 
## ##################################################
## # [------------------Covariances-----------------]
## 
## SE_Academic ~~ SE_Social
## 
## ##################################################
## # [--------Mediations (indirect effects)---------]
## 
## b1b7 := b1*b7
## b2b8 := b2*b8
## totalind_eltern := b1*b7 + b2*b8
## b3b7 := b3*b7
## b4b8 := b4*b8
## totalind_freunde := b3*b7 + b4*b8
## total_eltern := b1*b7 + b2*b8 + b5
## total_freunde := b3*b7 + b4*b8 + b6

Example 8 (intercepts)

Source: https://lavaan.ugent.be/tutorial/means.html

lavaan:

HS.model <- "
# three-factor model
  visual  =~ x1 + x2 + x3
  textual =~ x4 + x5 + x6
  speed   =~ x7 + x8 + x9
# intercepts with fixed values
  x1 + x2 + x3 + x4 ~ 0.5*1
"

lavaanExtra:

lat <- list(
  visual = paste0("x", 1:3),
  textual = paste0("x", 4:6),
  speed = paste0("x", 7:9)
)

cus <- "x1 + x2 + x3 + x4 ~ 0.5*1"

HS.model <- write_lavaan(
  latent = lat, custom = cus
)
cat(HS.model)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## visual =~ x1 + x2 + x3
## textual =~ x4 + x5 + x6
## speed =~ x7 + x8 + x9
## 
## ##################################################
## # [------------Custom Specifications-------------]
## 
## x1 + x2 + x3 + x4 ~ 0.5*1

Example 9 (thresholds)

Source: https://tdjorgensen.github.io/TDJorgensen/CatMeasEq/Jorgensen.CatMeasEq.pdf

lavaan:

mod2 <- "
## LIR means
  y2w1 ~ mean1*1
  y2w2 ~ mean2*1
## LIR (co)variances
  y2w1 ~~ var1*y2w1 + y2w2
  y2w2 ~~ var2*y2w2
## thresholds link LIRs to observed items
  y2w1 | thr1*t1
  y2w2 | thr2*t1
"

lavaanExtra:

reg <- list(
  y2w1 = "mean1*1",
  y2w2 = "mean2*1"
)

cov <- list(
  y2w1 = c("var1*y2w1", "y2w2"),
  y2w2 = "var2*y2w2"
)

thres <- list(
  y2w1 = "thr1*t1",
  y2w2 = "thr2*t1"
)

HS.model <- write_lavaan(
  regression = reg,
  covariance = cov,
  threshold = thres
)
cat(HS.model)
## ##################################################
## # [---------Regressions (Direct effects)---------]
## 
## y2w1 ~ mean1*1
## y2w2 ~ mean2*1
## 
## ##################################################
## # [------------------Covariances-----------------]
## 
## y2w1 ~~ var1*y2w1 + y2w2
## y2w2 ~~ var2*y2w2
## 
## ##################################################
## # [------------------Thresholds------------------]
## 
## y2w1 | thr1*t1
## y2w2 | thr2*t1

Example 10 (longitudinal invariance)

Source: https://thechangelab.stanford.edu/tutorials/growth-modeling/modeling-change-latent-vars-ordinal-indicators-lavaan/

lavaan:

configural_invar <- " #opening quote
#factor loadings
  eta1 =~ 1*t1_sc + #for identification
          t1_intp +
          t1_ext
  eta2 =~ 1*t2_sc + #for identification
          t2_intp +
          t2_ext
  eta3 =~ 1*t4_sc + #for identification
          t4_intp +
          t4_ext

#latent variable variances
   eta1~~eta1
   eta2~~eta2
   eta3~~eta3

#latent variable covariances
   eta1~~eta2
   eta1~~eta3
   eta2~~eta3

#latent variable means
   eta1~0*1 #for scaling
   eta2~0*1 #for scaling
   eta3~0*1 #for scaling

#propensity variances
   t1_sc  ~~ 1*t1_sc
   t1_intp~~ 1*t1_intp
   t1_ext ~~ 1*t1_ext
   t2_sc  ~~ 1*t2_sc
   t2_intp~~ 1*t2_intp
   t2_ext ~~ 1*t2_ext
   t4_sc  ~~ 1*t4_sc
   t4_intp~~ 1*t4_intp
   t4_ext ~~ 1*t4_ext

#unique covariances


#observed variable intercepts/thresholds (4 categories = 3 thresholds)
   t1_sc   |t1 + t2 + t3
   t1_intp |t1 + t2 + t3
   t1_ext  |t1 + t2 + t3
   t2_sc   |t1 + t2 + t3
   t2_intp |t1 + t2 + t3
   t2_ext  |t1 + t2 + t3
   t4_sc   |t1 + t2 + t3
   t4_intp |t1 + t2 + t3
   t4_ext  |t1 + t2 + t3
" # closing quote

lavaanExtra:

eta <- paste0("eta", 1:3)
t <- paste0("t", 1:4)
term <- c("sc", "intp", "ext")
tnames <- paste0(rep(t[c(1:2, 4)], each = 3), "_", term)
tnames2 <- paste0("1*", tnames)

lat <- list(
  eta1 = c(tnames2[1], tnames[2:3]),
  eta2 = c(tnames2[4], tnames[5:6]),
  eta3 = c(tnames2[7], tnames[8:9])
)

cov <- as.list(c(eta, eta[2:3], eta[3], tnames2))
names(cov) <- c(eta, eta[1], eta[1:2], tnames)

thres <- rep(list(t[1:3]), 9)
names(thres) <- tnames

reg <- as.list(setNames(rep("0*1", 3), eta))

HS.model <- write_lavaan(
  regression = reg,
  latent = lat,
  covariance = cov,
  threshold = thres
)
cat(HS.model)
## ##################################################
## # [-----Latent variables (measurement model)-----]
## 
## eta1 =~ 1*t1_sc + t1_intp + t1_ext
## eta2 =~ 1*t2_sc + t2_intp + t2_ext
## eta3 =~ 1*t4_sc + t4_intp + t4_ext
## 
## ##################################################
## # [---------Regressions (Direct effects)---------]
## 
## eta1 ~ 0*1
## eta2 ~ 0*1
## eta3 ~ 0*1
## 
## ##################################################
## # [------------------Covariances-----------------]
## 
## eta1 ~~ eta1
## eta2 ~~ eta2
## eta3 ~~ eta3
## eta1 ~~ eta2
## eta1 ~~ eta3
## eta2 ~~ eta3
## t1_sc ~~ 1*t1_sc
## t1_intp ~~ 1*t1_intp
## t1_ext ~~ 1*t1_ext
## t2_sc ~~ 1*t2_sc
## t2_intp ~~ 1*t2_intp
## t2_ext ~~ 1*t2_ext
## t4_sc ~~ 1*t4_sc
## t4_intp ~~ 1*t4_intp
## t4_ext ~~ 1*t4_ext
## 
## ##################################################
## # [------------------Thresholds------------------]
## 
## t1_sc | t1 + t2 + t3
## t1_intp | t1 + t2 + t3
## t1_ext | t1 + t2 + t3
## t2_sc | t1 + t2 + t3
## t2_intp | t1 + t2 + t3
## t2_ext | t1 + t2 + t3
## t4_sc | t1 + t2 + t3
## t4_intp | t1 + t2 + t3
## t4_ext | t1 + t2 + t3

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.