How to perform simplest Moderation in lavaan and measuring its effect to other vars?
You have a model in r, in lavaan - how you add an moderation term?:
Not a clear answer i found on web, in terms of simple words and example.
model_sem <-
'
a=~ x1 + x2
b=~ z1 + z2
a ~ b
'
Moderation = Testing if Interaction term is Significant or not (in Lavaan). This simple thing is not so clearly written to web with some exceptions. see here
When you have two observed variables (those that containing data) then the things are very simple
Let say you have X regressed onto (->) Y (X~Y) and M = Moderation variable
Note: that a simple lm syntax with interaction term is valid too. eg.
summary( lm( Y ~ X + X*Y ) )
library(psych)
library(dplyr)
library(lavaan)
library(semTools)
# Note that Centering variables is essential
# Creating interaction term prior of sem running
myData <- myData %>% mutate(Χ_x_Μ = myData$X * myData$M)
moderation_model <- '
# Hayes Process model 1
# regressions
Y ~ b1*X
Y ~ b2*M
Y ~ b3*Χ_x_Μ
# define mean parameter label for centered math for use in simple slopes
M ~ M.mean*1
# define variance parameter label for centered math for use in simple slopes
M ~~ M.var*M
# simple slopes for condition effect
SD.below := b1 + b3*(M.mean - sqrt(M.var))
mean := b1 + b3*(M.mean)
SD.above := b1 + b3*(M.mean + sqrt(M.var))
'
model <- moderation_model
sem_fit <- lavaan::sem( model, std.lv = TRUE, data = myData, fixed.x = FALSE )
summary( sem_fit, standardized = TRUE, rsquare = TRUE )
standardizedSolution( sem_fit, type = "std.all" )
However, things can go weird when you would like to interact 1st order or even 2nd order latent variables (ps. in some cases Factors). Because, Lavaan does not support this, in an easy way.
Steps:
# Create observed Factors by using their items
df$x1_o = (df$f11 + df$f12 + df$f13 ) /3
df$x2_o = (df$f21 + df$f22 + df$f33 ) /3
df$M_o = (df$m1 + df$m2 + df$m3 ) /3
df$Y_o = (df$y1 + df$y2 ) /3
df$X_o = (df$x1_o + df$x2_o ) /3
# Mean Center all your SEM variables
cn = colnames( df )
df_center = df - data.frame( matrix( rep( colMeans( df ), nrow( df ) ), ncol = ncol( df ), byrow = T)) # mean centering
colnames( df_center ) = cn
# Make to interact each item of Moderator (M) with the X Variable to test its effect on the Y variable
prod = df_center$x1_o * df_center$m1; df_center$prod11 = prod - mean(prod)
prod = df_center$x1_o * df_center$m2; df_center$prod12 = prod - mean(prod)
prod = df_center$x1_o * df_center$m3; df_center$prod13 = prod - mean(prod)
prod = df_center$x2_o * df_center$m1; df_center$prod11 = prod - mean(prod)
prod = df_center$x2_o * df_center$m2; df_center$prod12 = prod - mean(prod)
prod = df_center$x2_o * df_center$m3; df_center$prod13 = prod - mean(prod)
head(df_center, 2)
# Make your Lavaan moderated model
# Note that in defining mean and variance of (M) Moderator,
# we used the observed factored Moderator (M_o)
# and not the Latent (without values) construct (M).
# This happened cause Lavaan was saying that M.var has no free parameters.
# So, I did that. If you think something else, please make a comment or a
# post.
moderation_model <-
'
x1 = f11 + f12 + 13
x2 = f21 + f22 + f33
M = m1 + m2 + m3
Y = y1 + y2
X = x1 + x2
INT =~ prod11 + prod12 + prod13 + prod21 + prod22 + prod23
Y ~ b1 * X
Y ~ b2 * M
Y ~ b3 * INT
# define mean parameter label for centered math for use in simple slopes
M_o ~ M_o.mean*1
# define variance parameter label for centered math for use in simple slopes
M_o ~~ M_o.var*M_o
# simple slopes for condition effect
SD.below := b1 + b3*(M_o.mean - sqrt(M_o.var))
mean := b1 + b3*(M_o.mean)
SD.above := b1 + b3*(M_o.mean + sqrt(M_o.var))
'
# ps. If Lavaan says that there is non-definite matrix cause is negative,
# please, remove some items from the relevant variable from moderation model.
# Check if lavaan sem can run it:
model <- moderation_model
sem_fit <- lavaan::sem( model, std.lv = TRUE, data = df_center, fixed.x = FALSE )
summary( sem_fit, standardized = TRUE, rsquare = TRUE )
standardizedSolution( sem_fit, type = "std.all" )