# Chapter 4: Structural Equation Models

### Example 3 on Structural equation modelling: A multigroup model

Fit the structural equation model considered in the Examples 2 and 3, but now as a multigroup model fitted to the data from Denmark, Norway and Sweden (we limit the analysis to these countries to keep the example simple). Using likelihood ratio tests, examine if the regression coefficients in the structural model vary significantly between these countries. // A multigroup structural equation model, for three countries
gen DKNOSE=(cntry=="DK"|cntry=="NO"|cntry=="SE")
set matsize 5000
* First, fit the measurement models separately to
* obtain good starting values for fitting the full model
sem ///
(Effective -> plcpvcr plccbrg plcarcr) ///
(ProcFair -> plcrspc plcfrdc plcexdc) ///
if DKNOSE, ///
var(Effective@1) var(ProcFair@1) ///
method(mlmv)
matrix b=e(b)
sem ///
(Obey -> bplcdc doplcsy dpcstrb) ///
(MoralAlign -> plcrgwr plcipvl gsupplc) ///
if DKNOSE, ///
var(Obey@1) var(MoralAlign@1) ///
method(mlmv)
matrix b1=e(b)
matrix b=b,b1
sem ///
(Cooperation -> caplcst widprsn wevdct) ///
if DKNOSE, ///
var(Cooperation@1) ///
method(mlmv)
matrix b1=e(b)
matrix b=b,b1
// All structural parameters vary by country:
sem ///
(Effective -> plcpvcr@v1 plccbrg plcarcr) ///
(ProcFair -> plcrspc@v2 plcfrdc plcexdc) ///
(Obey -> bplcdc@v3 doplcsy dpcstrb) ///
(MoralAlign -> plcrgwr@v4 plcipvl gsupplc) ///
(Cooperation -> caplcst@v5 widprsn wevdct) ///
(Effective ProcFair -> Obey MoralAlign) ///
(20: _cons@v31 -> Obey) ///
(24: _cons@v32 -> Obey) ///
(20: _cons@v41 -> MoralAlign) ///
(24: _cons@v42 -> MoralAlign) ///
(Effective ProcFair Obey MoralAlign -> Cooperation) ///
(20: _cons@v51 -> Cooperation) ///
(24: _cons@v52 -> Cooperation) ///
if DKNOSE, ///
var(7: Effective@1) var(7: ProcFair@1) ///
var(7: e.Obey@1) var(7: e.MoralAlign@1) var(7: e.Cooperation@1) ///
cov(7: e.Obey*e.MoralAlign@v61) ///
cov(20: e.Obey*e.MoralAlign@v62) ///
cov(24: e.Obey*e.MoralAlign@v63) ///
method(mlmv) from(b,skip) ///
group(country) ginvariant(mcons mcoef merrvar)
estimates store allcoeffree
matrix b2=e(b)
// All structural regression coefficients are equal across countries:
sem ///
(Effective -> plcpvcr@v1 plccbrg plcarcr) ///
(ProcFair -> plcrspc@v2 plcfrdc plcexdc) ///
(Obey -> bplcdc@v3 doplcsy dpcstrb) ///
(MoralAlign -> plcrgwr@v4 plcipvl gsupplc) ///
(Cooperation -> caplcst@v5 widprsn wevdct) ///
(Effective ProcFair -> Obey MoralAlign) ///
(20: _cons@v31 -> Obey) ///
(24: _cons@v32 -> Obey) ///
(20: _cons@v41 -> MoralAlign) ///
(24: _cons@v42 -> MoralAlign) ///
(Effective ProcFair Obey MoralAlign-> Cooperation) ///
(20: _cons@v51 -> Cooperation) ///
(24: _cons@v52 -> Cooperation) ///
if DKNOSE, ///
var(7: Effective@1) var(7: ProcFair@1) ///
var(7: e.Obey@1) var(7: e.MoralAlign@1) var(7: e.Cooperation@1) ///
cov(7: e.Obey*e.MoralAlign@v61) ///
cov(20: e.Obey*e.MoralAlign@v62) ///
cov(24: e.Obey*e.MoralAlign@v63) ///
method(mlmv) from(b2,skip) ///
group(country) ginvariant(mcons mcoef merrvar scoef)
estimates store allcoefequal
// Comparing models where all coefficients vs. none vary by country:
lrtest allcoeffree allcoefequal # A multigroup structural equation model, for three countries
library(lavaan)
#
ind <- ESS5Police\$cntry=="DK" | ESS5Police\$cntry=="NO" | ESS5Police\$cntry=="SE"
#
ModelSyntax <- '
Effective =~ plcpvcr + plccbrg + plcarcr
ProcFair =~ plcrspc + plcfrdc + plcexdc
Obey =~ bplcdc + doplcsy + dpcstrb
MoralAlign =~ plcrgwr + plcipvl + gsupplc
Cooperation =~ caplcst + widprsn + wevdct
#
Obey + MoralAlign ~ Effective + ProcFair
Cooperation ~ Effective + ProcFair + Obey + MoralAlign
#
Obey ~~ MoralAlign
# Free latent variances and resid. variances across groups:
Effective ~~ c(1,NA,NA)*Effective
ProcFair ~~ c(1,NA,NA)*ProcFair
Obey ~~ c(1,NA,NA)* Obey
MoralAlign ~~ c(1,NA,NA)* MoralAlign
Cooperation ~~ c(1,NA,NA)* Cooperation
'
# All structural parameters vary by country:
FittedModel.allcoeffree <- sem(model = ModelSyntax,
data = ESS5Police[ind,],group="cntry",
std.lv = TRUE, meanstructure = TRUE,missing="ml",
## Concise table of estimated structural regression coefficients:
p.tmp<-parameterEstimates(FittedModel.allcoeffree,fmi=F)
p.tmp[p.tmp\$op=="~",]
# All structural regression coefficients are equal across countries:
FittedModel.allcoefequal <- sem(model = ModelSyntax,
data = ESS5Police[ind,],group="cntry",
std.lv = TRUE, meanstructure = TRUE,missing="ml", 