---
title: "Example lavaan models"
author: "Rémi Thériault"
date: "August 24, 2022"
output:
  rmarkdown::html_vignette:
    toc: true
vignette: >
  %\VignetteIndexEntry{Example lavaan models}
  %\VignetteEngine{knitr::rmarkdown}
---

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.

```{r, message = FALSE}
library(lavaan)
library(lavaanExtra)
```

## Example 1 (Model syntax 1): 
Source: https://lavaan.ugent.be/tutorial/syntax1.html

`lavaan`:
```{r}
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`:
```{r}
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)
```

## Example 2 (A CFA example): 
Source: https://lavaan.ugent.be/tutorial/cfa.html

`lavaan`:
```{r}
HS.model <- ' visual  =~ x1 + x2 + x3 
              textual =~ x4 + x5 + x6
              speed   =~ x7 + x8 + x9 '
```

`lavaanExtra`:
```{r}
lat <- list(visual = paste0("x", 1:3),
            textual = paste0("x", 4:6),
            speed = paste0("x", 7:9))
myModel <- write_lavaan(latent = lat)
cat(myModel)
```

## Example 3 (A SEM example): 
Source: https://lavaan.ugent.be/tutorial/sem.html

`lavaan`:
```{r}
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`:
```{r}
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)
```

## Example 4 (Model syntax 2): 
Source: https://lavaan.ugent.be/tutorial/syntax2.html

#### Example 4.1

`lavaan`:
```{r}
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`:
```{r}
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)
```

#### Example 4.2

`lavaan`:
```{r}
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`:
```{r}
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)
```

#### Example 4.3

`lavaan`:
```{r}
model <- '
f =~ y1 + y2 + myLabel*y3 + start(0.5)*y3 + y4
'
```

`lavaanExtra`:
```{r}
lat <- list(f = c("y1", "y2", "myLabel*y3", "start(0.5)*y3", "y4"))
model <- write_lavaan(latent = lat)
cat(model)
```

#### Example 4.4

`lavaan`:
```{r}
model <- '
visual  =~ x1 + v2*x2 + v2*x3
textual =~ x4 + x5 + x6
speed   =~ x7 + x8 + x9
'
```

`lavaanExtra`:
```{r}
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)
```

#### Example 4.5

`lavaan`:
```{r}
model <- '
visual  =~ x1 + x2 + equal("visual=~x2")*x3
textual =~ x4 + x5 + x6
speed   =~ x7 + x8 + x9
'
sem(model, data = HolzingerSwineford1939)
```

`lavaanExtra`:
```{r}
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)
sem(model, data = HolzingerSwineford1939)
```

#### Example 4.6

`lavaan`:
```{r}
model.constr <- ' # model with labeled parameters
                    y ~ b1*x1 + b2*x2 + b3*x3
                  # constraints
                    b1 == (b2 + b3)^2
                    b1 > exp(b2 + b3) '
```

`lavaanExtra`:
```{r}
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)
```

## Example 5 (Mediation)
Source: https://lavaan.ugent.be/tutorial/mediation.html

`lavaan`:
```{r}
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`:
```{r}
mediation <- list(Y = "c*X",
                  M = "a*X",
                  Y = "b*M")
indirect <- list(ab = "a*b",
                total = "c + (a*b)")
model <- write_lavaan(mediation, indirect = indirect)
cat(model)
```

## Example 6 (Multilevel SEM)
Source: https://lavaan.ugent.be/tutorial/multilevel.html

`lavaan`:
```{r}
model <- '
    level: 1
        fw =~ y1 + y2 + y3
        fw ~ x1 + x2 + x3
    level: 2
        fb =~ y1 + y2 + y3
        fb ~ w1 + w2
'
```

`lavaanExtra`:
```{r}
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)
```

# Example 7 (total effects)
Source: https://methodenlehre.github.io/SGSCLM-R-course/cfa-and-sem-with-lavaan.html#structural-equation-modelling-sem

`lavaan`:
```{r}
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`:

```{r}
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)
```
