# Example of Multiple Group Codes in lavaan ##################### Easy way ########################## ####################### WARNING ############################# # Do not use std.lv = TRUE in this easy way. It is wrong # ############################################################# library(lavaan) # Configural Invariance model <- ' visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 ' configural <- cfa(model, data=HolzingerSwineford1939, group="school") # Weak Invariance weak <- cfa(model, data=HolzingerSwineford1939, group="school", group.equal="loadings") # Weak invariance testing anova(configural, weak) # Strong Invariance strong <- cfa(model, data=HolzingerSwineford1939, group="school", group.equal=c("loadings", "intercepts")) # Strong invariance testing anova(weak, strong) # Factor Variance Invariance varin <- cfa(model, data=HolzingerSwineford1939, group="school", group.equal=c("loadings", "intercepts", "lv.variances")) # Omnibus test of invariance anova(strong, varin) # Test factor 1 variance model.varin1 <- ' # Constrain Only first factor variance with the same label visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 visual ~~ c(varvisual, varvisual)*visual ' varin1 <- cfa(model.varin1, data=HolzingerSwineford1939, group="school", group.equal=c("loadings", "intercepts")) # Test of variance 1. Do similary for Factors 2 and 3 anova(strong, varin1) # Covariance Invariance covin <- cfa(model, data=HolzingerSwineford1939, group="school", group.equal=c("loadings", "intercepts", "lv.covariances")) # Covariance invariance testing anova(strong, covin) # Test covariance between visual and textual model.covin1 <- ' # Constrain Only first factor variance with the same label visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 visual ~~ c(cov12, cov12)*textual ' covin1 <- cfa(model.covin1, data=HolzingerSwineford1939, group="school", group.equal=c("loadings", "intercepts")) # Covariance invariance testing anova(strong, covin1) # Test factor mean invariance meanin <- cfa(model, data=HolzingerSwineford1939, group="school", group.equal=c("loadings", "intercepts", "means")) # Factor means invariance testing anova(strong, meanin) # Test Factor Mean 1 model.meanin1 <- ' # Constrain Only first factor mean (visual) with the same label visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 visual ~ c(0, 0)*1 ' meanin1 <- cfa(model.meanin1, data=HolzingerSwineford1939, group="school", group.equal=c("loadings", "intercepts")) # Test for Factor Mean 1 difference. Do similarly for the other means anova(strong, meanin1) # Test for correlation difference # Lavaan currently (0.5-*) does not good for phantom variable approach for comparing correlations. # Use nonlinear constraints for comparing correlations instead model.corin <- ' # Label all factor variances and covariances # Change factor covariances of the first and second groups to correlation # Make a difference in correlation # Factor loadings visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 # Factor variances visual ~~ c(var11, var12)*visual textual ~~ c(var21, var22)*textual speed ~~ c(var31, var32)*speed # Factor covariances visual ~~ c(cov11, cov12)*textual visual ~~ c(cov21, cov22)*speed textual ~~ c(cov31, cov32)*speed # Factor correlations cor11 := cov11 / sqrt(var11 * var21) cor21 := cov21 / sqrt(var11 * var31) cor31 := cov31 / sqrt(var21 * var31) cor12 := cov12 / sqrt(var12 * var22) cor22 := cov22 / sqrt(var12 * var32) cor32 := cov32 / sqrt(var22 * var32) # Factor correlation difference diff1 := cor11 - cor12 diff2 := cor21 - cor22 diff3 := cor31 - cor32 ' corin <- cfa(model.corin, data=HolzingerSwineford1939, group="school", group.equal=c("loadings", "intercepts")) # Use bootstrap for testing factor correlation difference corinBoot <- cfa(model.corin, data=HolzingerSwineford1939, group="school", se="boot", group.equal=c("loadings", "intercepts")) parameterEstimates(corinBoot, boot.ci.type="bca.simple") ################################## Super Easy Way #################################3 library(semTools) model <- ' visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 ' # All analysis results are saved in a list allResults <- measurementInvariance(model, data=HolzingerSwineford1939, group="school") # To extract a lavaan object from a list, use double square brackets # See the description of each model in the screen summary(allResults[[1]]) # Configural Invariance summary(allResults[[2]]) # Weak Invariance summary(allResults[[3]]) # Strong Invariance summary(allResults[[4]]) # Factor Means Invariance