Lavaan - Example 5.1: Cross-Lagged Model with Observed Variables
Loading Libraries
library(MplusAutomation)
## Version: 0.7-3
## We work hard to write this free software. Please help us get credit by citing:
##
## Hallquist, M. N. & Wiley, J. F. (2018). MplusAutomation: An R Package for Facilitating Large-Scale Latent Variable Analyses in Mplus. Structural Equation Modeling, 25, 621-638. doi: 10.1080/10705511.2017.1402334.
##
## -- see citation("MplusAutomation").
library(texreg)
## Warning: package 'texreg' was built under R version 3.6.2
## Version: 1.37.5
## Date: 2020-06-17
## Author: Philip Leifeld (University of Essex)
##
## Consider submitting praise using the praise or praise_interactive functions.
## Please cite the JSS article in your publications -- see citation("texreg").
library(datasets)
library(lavaan)
## Warning: package 'lavaan' was built under R version 3.6.2
## This is lavaan 0.6-7
## lavaan is BETA software! Please report any bugs.
library(semPlot)
## Registered S3 methods overwritten by 'huge':
## method from
## plot.sim BDgraph
## print.sim BDgraph
library(readtext)
Preparing data for R
socex1.1 <- read.table("./Lista M6/Newsom_Ch5/Data/socex1.dat",header=FALSE)
Reading Lavaan Sintax
lav<-readtext::readtext("./Lista M6/Newsom_Ch5/R/ex5-1.R")
cat(lav$text)
## #title: Newsom Longitudinal SEM Chapter 5, Example 5.1
##
## library(lavaan)
## setwd("<your directory path")
## socex1.1 <- read.table ("socex1.dat", header=FALSE)
##
##
## names(socex1.1) = c("w1vst1", "w1vst2", "w1vst3", "w2vst1", "w2vst2",
## "w2vst3", "w3vst1", "w3vst2", "w3vst3", "w1unw1", "w1unw2", "w1unw3",
## "w2unw1", "w2unw2", "w2unw3", "w3unw1", "w3unw2", "w3unw3", "w1dboth",
## "w1dsad", "w1dblues", "w1ddep", "w2dboth", "w2dsad","w2dblues", "w2ddep",
## "w3dboth", "w3dsad", "w3dblues", "w3ddep", "w1marr2", "w1happy", "w1enjoy",
## "w1satis", "w1joyful", "w1please", "w2happy", "w2enjoy", "w2satis", "w2joyful",
## "w2please", "w3happy", "w3enjoy", "w3satis", "w3joyful", "w3please", "w1lea",
## "w2lea", "w3lea")
##
## #+++++++++++++++++++++++++++++++
## # Chapter 5, Example 5.1
## #+++++++++++++++++++++++++++++++
##
## attach(socex1.1)
##
## #define variables
##
## socex1.1$w1unw = (w1unw1 + w1unw2 + w1unw3)/3
## socex1.1$w2unw = (w2unw1 + w2unw2 + w2unw3)/3
## socex1.1$w1posaff = (w1happy + w1enjoy + w1satis + w1joyful + w1please)/5
## socex1.1$w2posaff = (w2happy + w2enjoy + w2satis + w2joyful + w2please)/5
##
## model5.2a <- ' #cross-lagged panel model with observed variables;
## w2unw ~ w1posaff + w1unw
## w2posaff ~ w1unw + w1posaff
## w1unw ~~ w1posaff
## w2unw ~~ w2posaff
## '
##
## fitmodel5.2a <- sem(model5.2a, data=socex1.1, information="expected")
## summary(fitmodel5.2a, fit.measures=TRUE, standardized=TRUE, rsquare=TRUE)
Naming Dataframe
names(socex1.1) = c("w1vst1", "w1vst2", "w1vst3", "w2vst1", "w2vst2",
"w2vst3", "w3vst1", "w3vst2", "w3vst3", "w1unw1", "w1unw2", "w1unw3",
"w2unw1", "w2unw2", "w2unw3", "w3unw1", "w3unw2", "w3unw3", "w1dboth",
"w1dsad", "w1dblues", "w1ddep", "w2dboth", "w2dsad","w2dblues", "w2ddep",
"w3dboth", "w3dsad", "w3dblues", "w3ddep", "w1marr2", "w1happy", "w1enjoy",
"w1satis", "w1joyful", "w1please", "w2happy", "w2enjoy", "w2satis", "w2joyful",
"w2please", "w3happy", "w3enjoy", "w3satis", "w3joyful", "w3please", "w1lea",
"w2lea", "w3lea")
Preparing Data
#+++++++++++++++++++++++++++++++
# Chapter 5, Example 5.1
#+++++++++++++++++++++++++++++++
# Makes socex1.1 default
attach(socex1.1)
#define variables
socex1.1$w1unw = (w1unw1 + w1unw2 + w1unw3)/3
socex1.1$w2unw = (w2unw1 + w2unw2 + w2unw3)/3
socex1.1$w1posaff = (w1happy + w1enjoy + w1satis + w1joyful + w1please)/5
socex1.1$w2posaff = (w2happy + w2enjoy + w2satis + w2joyful + w2please)/5
Lavaan Model
lavaan.model <-
'
#Cross-lagged panel model with observed variables;
# Regressions ON (~)
w2unw ~ w1posaff + w1unw
w2posaff ~ w1unw + w1posaff
# Co-variation WITH (~~)
w1unw ~~ w1posaff
w2unw ~~ w2posaff
'
Model Fit
lavaan.fit <- sem(lavaan.model, data=socex1.1, information="expected", estimator="ML")
Model Summary
summary(lavaan.fit, fit.measures=TRUE, standardized=TRUE, rsquare=TRUE)
## lavaan 0.6-7 ended normally after 21 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of free parameters 10
##
## Number of observations 574
##
## Model Test User Model:
##
## Test statistic 0.000
## Degrees of freedom 0
##
## Model Test Baseline Model:
##
## Test statistic 273.360
## Degrees of freedom 6
## P-value 0.000
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 1.000
## Tucker-Lewis Index (TLI) 1.000
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -2387.273
## Loglikelihood unrestricted model (H1) -2387.273
##
## Akaike (AIC) 4794.547
## Bayesian (BIC) 4838.073
## Sample-size adjusted Bayesian (BIC) 4806.327
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.000
## 90 Percent confidence interval - lower 0.000
## 90 Percent confidence interval - upper 0.000
## P-value RMSEA <= 0.05 NA
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.000
##
## Parameter Estimates:
##
## Standard errors Standard
## Information Expected
## Information saturated (h1) model Structured
##
## Regressions:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## w2unw ~
## w1posaff -0.199 0.050 -3.997 0.000 -0.199 -0.155
## w1unw 0.344 0.038 9.011 0.000 0.344 0.349
## w2posaff ~
## w1unw -0.029 0.030 -0.968 0.333 -0.029 -0.036
## w1posaff 0.490 0.039 12.436 0.000 0.490 0.465
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## w1posaff ~~
## w1unw -0.093 0.022 -4.222 0.000 -0.093 -0.179
## .w2unw ~~
## .w2posaff -0.043 0.018 -2.377 0.017 -0.043 -0.100
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .w2unw 0.546 0.032 16.941 0.000 0.546 0.835
## .w2posaff 0.343 0.020 16.941 0.000 0.343 0.777
## w1posaff 0.398 0.023 16.941 0.000 0.398 1.000
## w1unw 0.675 0.040 16.941 0.000 0.675 1.000
##
## R-Square:
## Estimate
## w2unw 0.165
## w2posaff 0.223
Fit Measures - Clean Output
lavaan.fit.measures<-as.data.frame(lavaan::fitmeasures(lavaan.fit, fit.measures = c("rmsea", "rmsea.ci.lower","rmsea.ci.upper","cfi","tli" )))
names(lavaan.fit.measures)[1]<-"Fit Measures"
print(lavaan.fit.measures)
## Fit Measures
## rmsea 0
## rmsea.ci.lower 0
## rmsea.ci.upper 0
## cfi 1
## tli 1
Parameters Estimate - Clean Output
fit.parameter<-lavaan::parameterestimates(lavaan.fit,output ="text", standardized =T,rsquare=T)
fit.parameter
##
## Regressions:
## Estimate Std.Err z-value P(>|z|) ci.lower ci.upper
## w2unw ~
## w1posaff -0.199 0.050 -3.997 0.000 -0.296 -0.101
## w1unw 0.344 0.038 9.011 0.000 0.269 0.419
## w2posaff ~
## w1unw -0.029 0.030 -0.968 0.333 -0.089 0.030
## w1posaff 0.490 0.039 12.436 0.000 0.413 0.567
## Std.lv Std.all
##
## -0.199 -0.155
## 0.344 0.349
##
## -0.029 -0.036
## 0.490 0.465
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) ci.lower ci.upper
## w1posaff ~~
## w1unw -0.093 0.022 -4.222 0.000 -0.136 -0.050
## .w2unw ~~
## .w2posaff -0.043 0.018 -2.377 0.017 -0.079 -0.008
## Std.lv Std.all
##
## -0.093 -0.179
##
## -0.043 -0.100
##
## Variances:
## Estimate Std.Err z-value P(>|z|) ci.lower ci.upper
## .w2unw 0.546 0.032 16.941 0.000 0.482 0.609
## .w2posaff 0.343 0.020 16.941 0.000 0.303 0.383
## w1posaff 0.398 0.023 16.941 0.000 0.352 0.444
## w1unw 0.675 0.040 16.941 0.000 0.596 0.753
## Std.lv Std.all
## 0.546 0.835
## 0.343 0.777
## 0.398 1.000
## 0.675 1.000
##
## R-Square:
## Estimate
## w2unw 0.165
## w2posaff 0.223
Basic Gray Plot
semPaths(lavaan.fit,whatLabel = "est", style="ram", what="path")

Colored and Weighted Plot
semPaths(lavaan.fit,whatLabel = "est", style="ram", what="est")

Updating Previous Lavaan Model
lavaan.model <-
'
#Cross-lagged panel model with observed variables;
# Regressions ON (~)
w2unw ~ w1posaff
w2posaff ~ w1unw + w1posaff
# Co-variation WITH (~~)
w1unw ~~ w1posaff
w2unw ~~ w2posaff
'
Updated Model Fit
lavaan.fit <- sem(lavaan.model, data=socex1.1, information="expected", estimator="MLR")
Updated Fit Measures - Clean Output
lavaan.fit.measures<-as.data.frame(lavaan::fitmeasures(lavaan.fit, fit.measures = c("rmsea", "rmsea.ci.lower","rmsea.ci.upper","cfi","tli" )))
names(lavaan.fit.measures)[1]<-"Fit Measures"
print(lavaan.fit.measures)
## Fit Measures
## rmsea 0.3613232
## rmsea.ci.lower 0.2950712
## rmsea.ci.upper 0.4323809
## cfi 0.7197105
## tli -0.6817368
Updated Parameters Estimate - Clean Output
fit.parameter<-lavaan::parameterestimates(lavaan.fit,output ="text", standardized =T,rsquare=T)
fit.parameter
##
## Regressions:
## Estimate Std.Err z-value P(>|z|) ci.lower ci.upper
## w2unw ~
## w1posaff -0.279 0.054 -5.186 0.000 -0.384 -0.173
## w2posaff ~
## w1unw -0.002 0.028 -0.074 0.941 -0.058 0.053
## w1posaff 0.496 0.038 12.900 0.000 0.421 0.572
## Std.lv Std.all
##
## -0.279 -0.217
##
## -0.002 -0.003
## 0.496 0.471
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) ci.lower ci.upper
## w1posaff ~~
## w1unw -0.093 0.021 -4.458 0.000 -0.134 -0.052
## .w2unw ~~
## .w2posaff -0.049 0.018 -2.673 0.008 -0.085 -0.013
## Std.lv Std.all
##
## -0.093 -0.179
##
## -0.049 -0.106
##
## Variances:
## Estimate Std.Err z-value P(>|z|) ci.lower ci.upper
## .w2unw 0.623 0.035 17.931 0.000 0.555 0.691
## .w2posaff 0.344 0.020 17.326 0.000 0.305 0.382
## w1posaff 0.398 0.025 16.117 0.000 0.350 0.446
## w1unw 0.675 0.034 19.559 0.000 0.607 0.742
## Std.lv Std.all
## 0.623 0.953
## 0.344 0.778
## 0.398 1.000
## 0.675 1.000
##
## R-Square:
## Estimate
## w2unw 0.047
## w2posaff 0.222
Updated Basic Gray Plot
semPaths(lavaan.fit,whatLabel = "est", style="ram", what="path")

Updated Colored and Weighted Plot
semPaths(lavaan.fit,whatLabel = "est", style="ram", what="est")

Mplus - Example 5.1: Cross-Lagged Model with Observed Variables
Reading original .inp file
inp<-readtext::readtext("./Lista M6/Newsom_Ch5/MPLUS/ex5-1a.inp")
cat(inp$text)
## title: Newsom Longitudinal SEM Chapter 5, Example 5.1,
## Cross-lagged Panel Models;
##
## data: file=socex1.dat; format=free;
##
## define:
## ! create equally weighted composites for unwanted advice
## ! and positive affect;
## w1unw = (w1unw1 + w1unw2 + w1unw3)/3;
## w2unw = (w2unw1 + w2unw2 + w2unw3)/3;
## w1posaff = (w1happy + w1enjoy + w1satis + w1joyful + w1please)/5;
## w2posaff = (w2happy + w2enjoy + w2satis + w2joyful + w2please)/5;
##
##
## variable:
## names=
## w1vst1 w1vst2 w1vst3
## w2vst1 w2vst2 w2vst3
## w3vst1 w3vst2 w3vst3
## w1unw1 w1unw2 w1unw3
## w2unw1 w2unw2 w2unw3
## w3unw1 w3unw2 w3unw3
## w1dboth w1dsad w1dblues w1ddep
## w2dboth w2dsad w2dblues w2ddep
## w3dboth w3dsad w3dblues w3ddep
## w1marr2
## w1happy w1enjoy w1satis w1joyful w1please
## w2happy w2enjoy w2satis w2joyful w2please
## w3happy w3enjoy w3satis w3joyful w3please
## w1lea w2lea w3lea;
##
## usevariables=
## w1posaff w2posaff w1unw w2unw;
##
## analysis: type=general;
## information=expected; model=nomeanstructure; !remove if means desired;
##
## model:
## !cross-lagged and autoregressive effects;
## w2posaff on w1posaff w1unw;
## w2unw on w1unw w1posaff;
##
## output: sampstat stdyx ;
Writing a Mplus Object using R
mplus.object<-mplusObject(
# Basic Mplus .inp
TITLE = NULL,
DATA = NULL,
VARIABLE = NULL,
DEFINE = NULL,
MONTECARLO = NULL,
MODELPOPULATION = NULL,
MODELMISSING = NULL,
ANALYSIS = NULL,
# Model
MODEL =
"w2posaff on w1posaff w1unw;
w2unw on w1unw w1posaff;",
MODELINDIRECT = NULL,
MODELCONSTRAINT = NULL,
MODELTEST = NULL,
MODELPRIORS = NULL,
# Output
OUTPUT = NULL,
SAVEDATA = NULL,
PLOT = NULL,
# R notation
usevariables = NULL, rdata =socex1.1, autov = TRUE, imputed = FALSE)
## R variables selected automatically as any variable name that
## occurs in the MODEL, VARIABLE, or DEFINE section.
## If any issues, suggest explicitly specifying USEVARIABLES.
## A starting point may be:
## USEVARIABLES = w1unw w2unw w1posaff w2posaff;
Creating a complete Mplus Object as a list in R
mplus.model<-mplusModeler(
# Sintaxe R
mplus.object,
# Dados formato R para formato .dat
dataout ="dados.dat",
# Sintaxe Mplus
modelout ="sintaxe.inp",
# Run one time
run=1)
## Wrote model to: sintaxe.inp
## File(s) with md5 hash matching data found, using
## dados_aab16c8f476c462166e677cdbfb8033f.dat
##
## Running model: sintaxe.inp
## System command: cd "." && "/Applications/Mplus/mplus" "sintaxe.inp"
## Reading model: sintaxe.out
Summary Basic Model
summary(mplus.model)
## Estimated using ML
## Number of obs: 574, number of (free) parameters: 9
##
## Model: Chi2(df = 0) = 0, p = 0
## Baseline model: Chi2(df = 5) = 254.661, p = 0
##
## Fit Indices:
##
## CFI = 1, TLI = 1, SRMR = 0
## RMSEA = 0, 90% CI [0, 0], p < .05 = 0
## AIC = 2308.202, BIC = 2347.376
Results Fit Indices
mplus.model.fit<-data.frame(
c(
mplus.model$results$summaries$RMSEA_Estimate,
mplus.model$results$summaries$RMSEA_90CI_LB,
mplus.model$results$summaries$RMSEA_90CI_UB,
mplus.model$results$summaries$CFI,
mplus.model$results$summaries$TLI)
)
names(mplus.model.fit)[1]<-"Fit Indices"
rownames(mplus.model.fit)<-c("RMSE Estimate","RMSEA 90 CI Lower","RMSEA 90 CI Upper","CFI","TLI")
mplus.model.fit
## Fit Indices
## RMSE Estimate 0
## RMSEA 90 CI Lower 0
## RMSEA 90 CI Upper 0
## CFI 1
## TLI 1
Results Parameters
mplus.model$results$parameters$unstandardized
## paramHeader param est se est_se pval
## 1 W2POSAFF.ON W1POSAFF 0.490 0.039 12.436 0.000
## 2 W2POSAFF.ON W1UNW -0.029 0.030 -0.968 0.333
## 3 W2UNW.ON W1UNW 0.344 0.038 9.011 0.000
## 4 W2UNW.ON W1POSAFF -0.199 0.050 -3.997 0.000
## 5 W2POSAFF.WITH W2UNW -0.043 0.018 -2.377 0.017
## 6 Intercepts W2UNW 1.905 0.183 10.417 0.000
## 7 Intercepts W2POSAFF 1.497 0.145 10.325 0.000
## 8 Residual.Variances W2UNW 0.546 0.032 16.941 0.000
## 9 Residual.Variances W2POSAFF 0.343 0.020 16.941 0.000
Updated Version
mplus.model.update<-update(
# Previous model
mplus.model,
# Changed Parameters
ANALYSIS = ~ + "ESTIMATOR = MLR;",
MODEL = ~
"w2posaff on w1posaff w1unw;
w2unw on w1posaff;"
)
## R variables selected automatically as any variable name that
## occurs in the MODEL, VARIABLE, or DEFINE section.
## If any issues, suggest explicitly specifying USEVARIABLES.
## A starting point may be:
## USEVARIABLES = w1unw w2unw w1posaff w2posaff;
Updated Running model
mplus.model.update<-mplusModeler(
# Sintaxe R
mplus.model.update,
# Dados formato R para formato .dat
dataout ="dados.dat",
# Sintaxe Mplus
modelout ="sintaxe.inp",
# Run one time
run=1)
## Wrote model to: sintaxe.inp
## File(s) with md5 hash matching data found, using
## dados_aab16c8f476c462166e677cdbfb8033f.dat
##
## Running model: sintaxe.inp
## System command: cd "." && "/Applications/Mplus/mplus" "sintaxe.inp"
## Reading model: sintaxe.out
Update Summary Models
summary(mplus.model.update)
## Estimated using MLR
## Number of obs: 574, number of (free) parameters: 8
##
## Model: Chi2(df = 1) = 77.57, p = 0
## Baseline model: Chi2(df = 5) = 267.438, p = 0
##
## Fit Indices:
##
## CFI = 0.708, TLI = -0.459, SRMR = 0.113
## RMSEA = 0.365, 90% CI [0.299, 0.436], p < .05 = 0
## AIC = 2382.14, BIC = 2416.961
Update Results Fit Indices
mplus.model.update.fit<-data.frame(
c(
mplus.model.update$results$summaries$RMSEA_Estimate,
mplus.model.update$results$summaries$RMSEA_90CI_LB,
mplus.model.update$results$summaries$RMSEA_90CI_UB,
mplus.model.update$results$summaries$CFI,
mplus.model.update$results$summaries$TLI)
)
names(mplus.model.update.fit)[1]<-"Fit Indices"
names(mplus.model.update.fit)[1]<-"Fit Indices"
rownames(mplus.model.update.fit)<-c("RMSE Estimate","RMSEA 90 CI Lower","RMSEA 90 CI Upper","CFI","TLI")
mplus.model.update.fit
## Fit Indices
## RMSE Estimate 0.365
## RMSEA 90 CI Lower 0.299
## RMSEA 90 CI Upper 0.436
## CFI 0.708
## TLI -0.459
Update Results Parameters
mplus.model.update$results$parameters$unstandardized
## paramHeader param est se est_se pval
## 1 W2POSAFF.ON W1POSAFF 0.496 0.039 12.885 0.000
## 2 W2POSAFF.ON W1UNW -0.002 0.030 -0.070 0.944
## 3 W2UNW.ON W1POSAFF -0.279 0.054 -5.186 0.000
## 4 W2POSAFF.WITH W2UNW -0.049 0.020 -2.524 0.012
## 5 Intercepts W2UNW 2.828 0.168 16.825 0.000
## 6 Intercepts W2POSAFF 1.424 0.147 9.697 0.000
## 7 Residual.Variances W2UNW 0.623 0.035 17.931 0.000
## 8 Residual.Variances W2POSAFF 0.344 0.020 17.322 0.000