13 CFA and SEM with lavaan
13.1 Confirmatory factor analysis (CFA)
lavaan
is a free open source package for latent variable modeling in R. The package is developed and maintained by Yves Rosseel (Rosseel, 2012; see also http://lavaan.ugent.be). The name lavaan
refers to latent variable analysis.
lavaan
can be used to estimate a variety of statistical models: path analysis, structural equation models (SEM) and confirmatory factor analyses (CFA).
13.1.1 Setup: Packages and data
::p_load(tidyverse, ggm, ggplot2, ggthemes, haven, lavaan, lavaanPlot, knitr, psych, semPlot, semTools, wesanderson) pacman
<- read_csv(
lifesat url("https://raw.githubusercontent.com/methodenlehre/data/master/lifesat.csv"))
## Rows: 275 Columns: 13
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): gender
## dbl (12): ID, age, school1, school2, school3, self1, self2, friends1, friend...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# convert ID and gender to factors
$ID <- as.factor(lifesat$ID)
lifesat$gender <- as.factor(lifesat$gender) lifesat
The life satisfaction data consist of 10 items related to different aspects/domains of life satisfaction. The adolescents were asked:
“How satisfied are you with…?”
Items | |
---|---|
school1 | your school grade |
school2 | your relationship with your teacher |
school3 | your school life |
self1 | your looks and appearance |
self2 | your personality |
friends1 | your social life |
friends2 | your relationships with your friends |
fam1 | your relationship with your parents |
fam2 | your family life |
fam3 | your socio-economic status |
The response was on a 7-point scale from 1 = “not satisfied at all” to 7 = “very satisfied”.
The questions on life satisfaction can be divided into four domains: school, self, friends, family
The ML estimation assumes a multivariate normal distribution. Let’s first look at the univariate skewness and kurtosis using describe()
from psych
:
<- lifesat[-(1:3)] %>%
check_cfa describe()
$skew check_cfa
## [1] -0.7159340 -0.7609000 -0.6756997 -1.0303710 -1.5071008 -1.2017037
## [7] -0.8989515 -1.6183389 -1.4575230 -1.4230322
$kurtosis check_cfa
## [1] 0.2828551 0.8154313 0.2107045 1.1177822 3.7815521 3.5733595 0.4539949
## [8] 3.0151001 3.0209721 3.1563637
Serious deviations from the normal distribution are present if the skewness of the manifest variables is greater than an absolute value of 2 and the (excess) kurtosis is greater than 4.
We can check multivariate skewness and kurtosis (Mardia’s coefficients):
-(1:3)] %>%
lifesat[mardiaSkew()
## b1d chi df p
## 2.832089e+01 1.298041e+03 2.200000e+02 3.893895e-152
-(1:3)] %>%
lifesat[mardiaKurtosis()
## b2d z p
## 1.842232e+02 3.437339e+01 6.300872e-259
According to these cutoffs our items do not seem to be very problematic univariately, but both multivariate skewness and kurtosis are very high, pointing to multivariate outliers that might inflate standard errors of coefficients (coefficients themselves are mostly unaffected by non-normality).
We will therefore request additional estimation methods as well as bootstrap analysis to account for non-normality.
13.1.2 Defining the CFA model in lavaan
The calculation of a CFA with lavaan
is done in two steps:
A model defining the hypothesized factor structure is set up
This model is estimated using
cfa()
, which takes as input both the data and the model definition. Model definitions inlavaan
all follow the same type of syntax.
In the model definition syntax, certain characters (operators) are predefined and a number of default settings are applied. For example, by default the scaling of the latent variable is achieved by fixing the loading of the first indicator (manifest variable) for a latent variable to the value of 1
.
=~
indicates that the latent variable (here named Factor1
) to the left of the operator is defined by all variables to the right of it. The manifest (measured) variables from the dataset on the right are separated by a +
.
An example of six items explained by two factors (latent variables):
<- "
example_model Factor1 =~ var1 + var2 + var3
Factor2 =~ var4 + var5 + var6
# The order of the manifest variables is relevant only for fixing one loading per factor.
# Here the loadings of `var1` and `var4` are set to the value 1.
# Comments like this are ignored by lavaan.
"
The parameters of the model do not have to be explicitly defined (e.g. l12
for the loading of the second item (var2)
on the first factor (Factor1)
. However, they can be defined explicitly and we will see that this will be necessary in some situations.
Another default is that factor variances and covariances are automatically specified for all latent variables in a CFA. The operator for specifying a variance/covariance is ~~
. Variances are defined as covariances of a variable with itself. Thus, in this example we could add the lines Factor1 ~~ Factor1
, Factor2 ~~ Factor2
(latent variable variances), and Factor1 ~~ Factor2
(latent variable covariance) without changing the model definition. The same holds for the residual variances of the manifest variables (but not for potential residual covariances!).
13.1.3 Estimating the model
Syntax for estimation:
cfa(model = example_model, data = dataframe)
The direct execution of this syntax results in only a very limited output, containing only the number of estimated parameters, the number of observations, and the chi-square statistics.
Therefore, like with lm()
the result of cfa()
must first be assigned to an output object (e.g. fit_example_model
) and the detailed output (including the parameter estimates) extracted with summary()
.
Additional arguments of the summary()
function : fit.measures = TRUE
returns a number of global fit indices (e.g. SRMR, RMSEA, CLI, TLI) as well as information criteria (e.g. AIC and BIC), and with standardized = TRUE
we obtain both the unstandardized and the standardized parameter estimates.
13.1.4 Life satisfaction CFA with four factors
For theoretical reasons, we first estimate a model with four factors. We define one factor for each content domain of life satisfaction (school, self, friends, family). In addition, as usual we postulate a simple structure, i.e. all potential cross-loadings are restricted to the value of 0 (i.e., in the model definition manifest variables only appear once - in the equation of their respective factor).
The theoretical model looks like this:
semPaths(fit_mod4f)
Modell definition
<- "
model_4f school =~ school1 + school2 + school3
self =~ self1 + self2
friends =~ friends1 + friends2
family =~ fam1 + fam2 + fam3
"
Model estimation
Because of the multivariate non-normality of the data we use an alternative maximum-likelihood estimation method - robust ML. As noted above the parameter estimates themselves are usually unbiased also under non-normality but the standard errors are not.
Thus, we estimate the parameters with regular ML but with robust (and therefore greater) standard errors that correct for non-normality (se = "robust"
).
Furthermore, we use a robust scaled chi-square test statistic (test = "Satorra-Bentler"
) that corrects for the fact that for non-normal data the usual model test statistic tends to be too large. The Satorra-Bentler test rescales the value of the ML chi-square test according to the degree of multivariate kurtosis of the data.
The combination of se = "robust"
and test = "Satorra-Bentler"
can be called with estimator = "MLM
:
<- cfa(model_4f,
fit_mod4f data = lifesat,
estimator = "MLM")
semPaths(fit_mod4f, "std")
summary(fit_mod4f, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 46 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 26
##
## Number of observations 275
##
## Model Test User Model:
## Standard Robust
## Test Statistic 68.209 47.000
## Degrees of freedom 29 29
## P-value (Chi-square) 0.000 0.019
## Scaling correction factor 1.451
## Satorra-Bentler correction
##
## Model Test Baseline Model:
##
## Test statistic 725.606 420.551
## Degrees of freedom 45 45
## P-value 0.000 0.000
## Scaling correction factor 1.725
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.942 0.952
## Tucker-Lewis Index (TLI) 0.911 0.926
##
## Robust Comparative Fit Index (CFI) 0.960
## Robust Tucker-Lewis Index (TLI) 0.937
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4064.982 -4064.982
## Loglikelihood unrestricted model (H1) -4030.877 -4030.877
##
## Akaike (AIC) 8181.964 8181.964
## Bayesian (BIC) 8276.000 8276.000
## Sample-size adjusted Bayesian (BIC) 8193.559 8193.559
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.070 0.048
## 90 Percent confidence interval - lower 0.049 0.025
## 90 Percent confidence interval - upper 0.092 0.068
## P-value RMSEA <= 0.05 0.061 0.556
##
## Robust RMSEA 0.057
## 90 Percent confidence interval - lower 0.024
## 90 Percent confidence interval - upper 0.086
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.059 0.059
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Structured
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school =~
## school1 1.000 0.635 0.444
## school2 1.300 0.279 4.669 0.000 0.826 0.625
## school3 1.834 0.357 5.144 0.000 1.165 0.830
## self =~
## self1 1.000 0.924 0.700
## self2 0.993 0.164 6.058 0.000 0.917 0.806
## friends =~
## friends1 1.000 0.886 0.869
## friends2 0.453 0.148 3.059 0.002 0.401 0.494
## family =~
## fam1 1.000 1.017 0.769
## fam2 1.051 0.149 7.048 0.000 1.069 0.872
## fam3 0.629 0.117 5.399 0.000 0.640 0.572
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school ~~
## self 0.141 0.065 2.167 0.030 0.240 0.240
## friends 0.177 0.056 3.158 0.002 0.315 0.315
## family 0.246 0.072 3.427 0.001 0.381 0.381
## self ~~
## friends 0.419 0.092 4.563 0.000 0.512 0.512
## family 0.355 0.129 2.754 0.006 0.378 0.378
## friends ~~
## family 0.321 0.111 2.888 0.004 0.356 0.356
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .school1 1.639 0.177 9.249 0.000 1.639 0.803
## .school2 1.066 0.207 5.143 0.000 1.066 0.610
## .school3 0.613 0.281 2.180 0.029 0.613 0.311
## .self1 0.886 0.172 5.159 0.000 0.886 0.510
## .self2 0.453 0.175 2.595 0.009 0.453 0.350
## .friends1 0.255 0.218 1.173 0.241 0.255 0.245
## .friends2 0.499 0.060 8.285 0.000 0.499 0.756
## .fam1 0.714 0.152 4.685 0.000 0.714 0.408
## .fam2 0.359 0.119 3.029 0.002 0.359 0.239
## .fam3 0.842 0.121 6.944 0.000 0.842 0.672
## school 0.403 0.120 3.369 0.001 1.000 1.000
## self 0.853 0.212 4.016 0.000 1.000 1.000
## friends 0.784 0.276 2.842 0.004 1.000 1.000
## family 1.035 0.228 4.533 0.000 1.000 1.000
Local model fit: Comparing the empirical and implied variance-covariance matrix
The lavInspect()
function allows extracting information from a lavaan
object. The argument what
specifies which information should be extracted. The value sampstat
of this argument stands for “sample statistics”, the empirical variance-covariance matrix:
lavInspect(fit_mod4f, what = "sampstat")
## $cov
## schol1 schol2 schol3 self1 self2 frnds1 frnds2 fam1 fam2 fam3
## school1 2.042
## school2 0.473 1.748
## school3 0.705 0.990 1.969
## self1 0.305 0.240 0.409 1.739
## self2 0.262 0.040 0.182 0.847 1.294
## friends1 0.261 0.108 0.375 0.369 0.437 1.039
## friends2 0.037 0.063 0.094 0.167 0.221 0.356 0.660
## fam1 0.543 0.231 0.434 0.437 0.385 0.307 0.189 1.749
## fam2 0.540 0.327 0.369 0.378 0.261 0.331 0.150 1.103 1.502
## fam3 0.353 0.314 0.391 0.477 0.369 0.231 0.103 0.575 0.693 1.252
The variance-covariance matrix implied by the model is obtained with what = "implied"
:
lavInspect(fit_mod4f, what = "implied")
## $cov
## schol1 schol2 schol3 self1 self2 frnds1 frnds2 fam1 fam2 fam3
## school1 2.042
## school2 0.525 1.748
## school3 0.740 0.962 1.969
## self1 0.141 0.183 0.258 1.739
## self2 0.140 0.182 0.256 0.847 1.294
## friends1 0.177 0.230 0.324 0.419 0.416 1.039
## friends2 0.080 0.104 0.147 0.190 0.189 0.356 0.660
## fam1 0.246 0.320 0.452 0.355 0.352 0.321 0.145 1.749
## fam2 0.259 0.337 0.475 0.373 0.370 0.337 0.153 1.088 1.502
## fam3 0.155 0.202 0.284 0.223 0.222 0.202 0.092 0.651 0.685 1.252
The smaller the differences between these two matrices, the better the model fits the data. In other words, the closer are the variances and covariances recalculated from the estimated parameters to the empirical variances and covariances.
The residual matrix results from the subtraction of the variance-covariance matrix implied by the model from the observed (empirical) variance-covariance matrix.
<-
residual_matrix lavInspect(fit_mod4f, what = "sampstat")$cov -
lavInspect(fit_mod4f, what = "implied")$cov
residual_matrix
## schol1 schol2 schol3 self1 self2 frnds1 frnds2 fam1 fam2 fam3
## school1 0.000
## school2 -0.052 0.000
## school3 -0.035 0.028 0.000
## self1 0.164 0.057 0.151 0.000
## self2 0.122 -0.141 -0.074 0.000 0.000
## friends1 0.084 -0.122 0.051 -0.050 0.021 0.000
## friends2 -0.043 -0.042 -0.053 -0.022 0.033 0.000 0.000
## fam1 0.296 -0.090 -0.018 0.082 0.033 -0.014 0.044 0.000
## fam2 0.281 -0.009 -0.106 0.005 -0.110 -0.006 -0.003 0.015 0.000
## fam3 0.198 0.113 0.107 0.254 0.147 0.029 0.011 -0.076 0.008 0.000
A direct extraction of the residual matrix can be obtained with the argument what = "resid"
:
lavInspect(fit_mod4f, what = "resid")
## $cov
## schol1 schol2 schol3 self1 self2 frnds1 frnds2 fam1 fam2 fam3
## school1 0.000
## school2 -0.052 0.000
## school3 -0.035 0.028 0.000
## self1 0.164 0.057 0.151 0.000
## self2 0.122 -0.141 -0.074 0.000 0.000
## friends1 0.084 -0.122 0.051 -0.050 0.021 0.000
## friends2 -0.043 -0.042 -0.053 -0.022 0.033 0.000 0.000
## fam1 0.296 -0.090 -0.018 0.082 0.033 -0.014 0.044 0.000
## fam2 0.281 -0.009 -0.106 0.005 -0.110 -0.006 -0.003 0.015 0.000
## fam3 0.198 0.113 0.107 0.254 0.147 0.029 0.011 -0.076 0.008 0.000
Particularly relevant for the local fit diagnostics is the variance-covariance matrix of standardized residuals, which can be obtained using resid()
:
resid(fit_mod4f, type = "standardized")
## $type
## [1] "standardized"
##
## $cov
## schol1 schol2 schol3 self1 self2 frnds1 frnds2 fam1 fam2 fam3
## school1 0.000
## school2 -0.928 0.000
## school3 -1.377 2.455 0.000
## self1 1.298 0.666 2.090 0.000
## self2 1.041 -2.350 -1.902 0.000 0.000
## friends1 1.018 -1.923 1.806 -1.874 1.411 0.000
## friends2 -0.697 -0.669 -0.879 -0.628 1.025 0.000 0.000
## fam1 2.441 -1.032 -0.265 1.083 0.684 -0.231 0.778 0.000
## fam2 2.443 -0.148 -3.192 0.098 -3.052 -0.176 -0.057 2.790 0.000
## fam3 1.682 1.313 1.334 2.767 2.056 0.384 0.205 -3.015 0.662 0.000
Global model fit
For the robust CFI = 0.96 and NNFI/TLI = 0.937 values close the recommended cut-off criteria of 0.97/0.95 resulted. The RMSEA = 0.057 is slightly above the cut-off of 0.05, but it is not significantly greater than 0.05 (90 % CI = [0.024; 0.086]).
13.1.4.1 Bootstrapping
Another robust estimation method is using a nonparametric bootstrap for the standard errors. In this procedure the parameter estimates themselves are those from the regular ML estimation, but the standard errors of the parameters are obtained from (e.g.) 1000 bootstrap samples (sampled directly from the data).
The arguments needed for the estimation are: se = "bootstrap", verbose = TRUE, bootstrap = 1000
Additionally, the chi-square test statistic can also be bootstrapped. However, this cannot be done via the chi-square statistics from the nonparametric bootstrap already carried out to obtain standard errors of the parameter estimates. This is due to the fact that in addition to non-normality the test statistic is influenced by model misfit (and of course sampling variability). An adjusted version that can be bootstrapped is known as the Bollen-Stine bootstrap which can be obtained using the argument: test = "bootstrap"
Let’s try it:
<- cfa(model_4f,
fit_mod4f_boot data = lifesat,
se = "bootstrap",
test = "bootstrap",
verbose = FALSE,
bootstrap = 1000)
summary(fit_mod4f_boot, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 46 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 26
##
## Number of observations 275
##
## Model Test User Model:
##
## Test statistic 68.209
## Degrees of freedom 29
## P-value (Chi-square) 0.000
##
## Test statistic 68.209
## Degrees of freedom 29
## P-value (Bollen-Stine bootstrap) 0.022
##
## Model Test Baseline Model:
##
## Test statistic 725.606
## Degrees of freedom 45
## P-value 0.000
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.942
## Tucker-Lewis Index (TLI) 0.911
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4064.982
## Loglikelihood unrestricted model (H1) -4030.877
##
## Akaike (AIC) 8181.964
## Bayesian (BIC) 8276.000
## Sample-size adjusted Bayesian (BIC) 8193.559
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.070
## 90 Percent confidence interval - lower 0.049
## 90 Percent confidence interval - upper 0.092
## P-value RMSEA <= 0.05 0.061
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.059
##
## Parameter Estimates:
##
## Standard errors Bootstrap
## Number of requested bootstrap draws 1000
## Number of successful bootstrap draws 1000
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school =~
## school1 1.000 0.635 0.444
## school2 1.300 0.285 4.557 0.000 0.826 0.625
## school3 1.834 0.401 4.569 0.000 1.165 0.830
## self =~
## self1 1.000 0.924 0.700
## self2 0.993 0.175 5.673 0.000 0.917 0.806
## friends =~
## friends1 1.000 0.886 0.869
## friends2 0.453 0.157 2.882 0.004 0.401 0.494
## family =~
## fam1 1.000 1.017 0.769
## fam2 1.051 0.147 7.151 0.000 1.069 0.872
## fam3 0.629 0.110 5.718 0.000 0.640 0.572
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school ~~
## self 0.141 0.064 2.192 0.028 0.240 0.240
## friends 0.177 0.053 3.308 0.001 0.315 0.315
## family 0.246 0.066 3.741 0.000 0.381 0.381
## self ~~
## friends 0.419 0.092 4.566 0.000 0.512 0.512
## family 0.355 0.131 2.715 0.007 0.378 0.378
## friends ~~
## family 0.321 0.104 3.092 0.002 0.356 0.356
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .school1 1.639 0.178 9.188 0.000 1.639 0.803
## .school2 1.066 0.188 5.657 0.000 1.066 0.610
## .school3 0.613 0.286 2.141 0.032 0.613 0.311
## .self1 0.886 0.177 4.994 0.000 0.886 0.510
## .self2 0.453 0.180 2.520 0.012 0.453 0.350
## .friends1 0.255 0.308 0.829 0.407 0.255 0.245
## .friends2 0.499 0.061 8.217 0.000 0.499 0.756
## .fam1 0.714 0.138 5.160 0.000 0.714 0.408
## .fam2 0.359 0.107 3.345 0.001 0.359 0.239
## .fam3 0.842 0.119 7.064 0.000 0.842 0.672
## school 0.403 0.125 3.236 0.001 1.000 1.000
## self 0.853 0.211 4.050 0.000 1.000 1.000
## friends 0.784 0.350 2.239 0.025 1.000 1.000
## family 1.035 0.220 4.696 0.000 1.000 1.000
The bootstrap confidence intervals can be obtained with:
parameterEstimates(fit_mod4f_boot)
## lhs op rhs est se z pvalue ci.lower ci.upper
## 1 school =~ school1 1.000 0.000 NA NA 1.000 1.000
## 2 school =~ school2 1.300 0.285 4.557 0.000 0.863 1.977
## 3 school =~ school3 1.834 0.401 4.569 0.000 1.268 2.882
## 4 self =~ self1 1.000 0.000 NA NA 1.000 1.000
## 5 self =~ self2 0.993 0.175 5.673 0.000 0.695 1.399
## 6 friends =~ friends1 1.000 0.000 NA NA 1.000 1.000
## 7 friends =~ friends2 0.453 0.157 2.882 0.004 0.189 0.809
## 8 family =~ fam1 1.000 0.000 NA NA 1.000 1.000
## 9 family =~ fam2 1.051 0.147 7.151 0.000 0.832 1.397
## 10 family =~ fam3 0.629 0.110 5.718 0.000 0.452 0.874
## 11 school1 ~~ school1 1.639 0.178 9.188 0.000 1.298 1.997
## 12 school2 ~~ school2 1.066 0.188 5.657 0.000 0.659 1.412
## 13 school3 ~~ school3 0.613 0.286 2.141 0.032 -0.045 1.129
## 14 self1 ~~ self1 0.886 0.177 4.994 0.000 0.524 1.217
## 15 self2 ~~ self2 0.453 0.180 2.520 0.012 0.104 0.832
## 16 friends1 ~~ friends1 0.255 0.308 0.829 0.407 -0.539 0.542
## 17 friends2 ~~ friends2 0.499 0.061 8.217 0.000 0.366 0.603
## 18 fam1 ~~ fam1 0.714 0.138 5.160 0.000 0.453 0.980
## 19 fam2 ~~ fam2 0.359 0.107 3.345 0.001 0.119 0.547
## 20 fam3 ~~ fam3 0.842 0.119 7.064 0.000 0.608 1.081
## 21 school ~~ school 0.403 0.125 3.236 0.001 0.197 0.686
## 22 self ~~ self 0.853 0.211 4.050 0.000 0.505 1.332
## 23 friends ~~ friends 0.784 0.350 2.239 0.025 0.399 1.702
## 24 family ~~ family 1.035 0.220 4.696 0.000 0.650 1.502
## 25 school ~~ self 0.141 0.064 2.192 0.028 0.030 0.280
## 26 school ~~ friends 0.177 0.053 3.308 0.001 0.075 0.283
## 27 school ~~ family 0.246 0.066 3.741 0.000 0.123 0.378
## 28 self ~~ friends 0.419 0.092 4.566 0.000 0.238 0.605
## 29 self ~~ family 0.355 0.131 2.715 0.007 0.137 0.650
## 30 friends ~~ family 0.321 0.104 3.092 0.002 0.129 0.534
How do the bootstrap standard errors differ from the robust standard errors?
parameterEstimates(fit_mod4f_boot)[5] - parameterEstimates(fit_mod4f)[5]
## se
## 1 0.00000000000
## 2 0.00684364003
## 3 0.04491955108
## 4 0.00000000000
## 5 0.01113183390
## 6 0.00000000000
## 7 0.00909382834
## 8 0.00000000000
## 9 -0.00214186034
## 10 -0.00650287867
## 11 0.00116850726
## 12 -0.01883479762
## 13 0.00505013290
## 14 0.00568113362
## 15 0.00523463190
## 16 0.09011899523
## 17 0.00050081940
## 18 -0.01402725052
## 19 -0.01118555365
## 20 -0.00205559487
## 21 0.00492448486
## 22 -0.00177000142
## 23 0.07432722773
## 24 -0.00794516090
## 25 -0.00073467248
## 26 -0.00253588982
## 27 -0.00602335882
## 28 -0.00006798647
## 29 0.00181433491
## 30 -0.00732472622
And how do they both differ from normal theory standard errors?
# Fit model with normal theory standard errors
<- cfa(model_4f,
fit_mod4f_normal data = lifesat)
# Sum of the absolute differences in standard errors between the bootstrap se and the robust se models
sum(as.vector(abs(parameterEstimates(fit_mod4f_boot)[5] - parameterEstimates(fit_mod4f)[5])))
## [1] 0.3419589
# Sum of the absolute differences in standard errors between the normal theory and the bootstrap se models
sum(as.vector(abs(parameterEstimates(fit_mod4f_normal)[5] - parameterEstimates(fit_mod4f_boot)[5])))
## [1] 1.213326
# Sum of the absolute differences in standard errors between the normal theory and the robust se models
sum(as.vector(abs(parameterEstimates(fit_mod4f_normal)[5] - parameterEstimates(fit_mod4f)[5])))
## [1] 1.038189
As expected, bootstrap and robust standard errors are similar to each other while they differ both substantially from the normal theory standard errors!
13.1.4.2 Life satisfaction ratings as ordered categories
Another option for robust estimation is to not view the Likert-type variables as continuous but as ordinal. This is achieved by the argument ordered = c("var1", "var2", "var3" etc...)
in the estimation function.
In this case lavaan
offers an estimation based on the polychoric correlations of the variables using a multi-stage weighted least-square estimation.
The default method is estimator = "WLSMV"
which adds a robust version to the diagonally weighted least squares approach (DWLS).
Before we fit the model we should make sure that all the categories (from 1-7) have adequate cell frequencies:
# convert all items to factors
<- lifesat[, -(1:3)] %>% mutate_all(as_factor)
lifesat_cat # return frequencies
summary(lifesat_cat)
## school1 school2 school3 self1 self2 friends1 friends2 fam1 fam2
## 1:12 1: 9 1:16 1: 7 1: 5 1: 3 3: 1 1: 7 1: 6
## 2: 7 2: 9 2:10 2: 3 2: 1 2: 1 4: 7 2: 2 2: 2
## 3:30 3: 16 3:32 3: 19 3: 4 3: 3 5: 39 3: 7 3: 4
## 4:50 4: 61 4:67 4: 37 4: 20 4: 18 6:107 4: 18 4: 27
## 5:88 5:101 5:91 5: 72 5: 67 5: 92 7:121 5: 47 5: 58
## 6:66 6: 58 6:49 6:103 6:118 6:111 6: 94 6:114
## 7:22 7: 21 7:10 7: 34 7: 60 7: 47 7:100 7: 64
## fam3
## 1: 3
## 2: 2
## 3: 4
## 4: 20
## 5: 54
## 6:115
## 7: 77
As the frequencies for categories 1 and 2 are very low for almost all items we may join the categories 1 and 2 with category 3 for all items:
<- lifesat_cat %>% mutate_at(names(lifesat_cat), ~fct_recode(.x, "3" = "1", "3" = "2")) lifesat_rec
## Warning: Unknown levels in `f`: 1, 2
summary(lifesat_rec)
## school1 school2 school3 self1 self2 friends1 friends2 fam1 fam2
## 3:49 3: 34 3:58 3: 29 3: 10 3: 7 3: 1 3: 16 3: 12
## 4:50 4: 61 4:67 4: 37 4: 20 4: 18 4: 7 4: 18 4: 27
## 5:88 5:101 5:91 5: 72 5: 67 5: 92 5: 39 5: 47 5: 58
## 6:66 6: 58 6:49 6:103 6:118 6:111 6:107 6: 94 6:114
## 7:22 7: 21 7:10 7: 34 7: 60 7: 47 7:121 7:100 7: 64
## fam3
## 3: 9
## 4: 20
## 5: 54
## 6:115
## 7: 77
Now let’s fit the model:
<- cfa(model_4f,
fit_mod4f_ordered data = lifesat_rec,
ordered = c("school1", "school2", "school3",
"self1", "self2", "friends1", "friends2",
"fam1", "fam2", "fam3"),
estimator = "WLSMV")
summary(fit_mod4f_ordered, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 31 iterations
##
## Estimator DWLS
## Optimization method NLMINB
## Number of model parameters 56
##
## Number of observations 275
##
## Model Test User Model:
## Standard Robust
## Test Statistic 40.772 62.883
## Degrees of freedom 29 29
## P-value (Chi-square) 0.072 0.000
## Scaling correction factor 0.714
## Shift parameter 5.793
## simple second-order correction
##
## Model Test Baseline Model:
##
## Test statistic 2240.595 1466.489
## Degrees of freedom 45 45
## P-value 0.000 0.000
## Scaling correction factor 1.545
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.995 0.976
## Tucker-Lewis Index (TLI) 0.992 0.963
##
## Robust Comparative Fit Index (CFI) NA
## Robust Tucker-Lewis Index (TLI) NA
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.038 0.065
## 90 Percent confidence interval - lower 0.000 0.043
## 90 Percent confidence interval - upper 0.064 0.087
## P-value RMSEA <= 0.05 0.743 0.120
##
## Robust RMSEA NA
## 90 Percent confidence interval - lower NA
## 90 Percent confidence interval - upper NA
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.050 0.050
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Unstructured
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school =~
## school1 1.000 0.563 0.563
## school2 1.118 0.139 8.015 0.000 0.630 0.630
## school3 1.546 0.201 7.678 0.000 0.871 0.871
## self =~
## self1 1.000 0.707 0.707
## self2 1.206 0.128 9.405 0.000 0.853 0.853
## friends =~
## friends1 1.000 0.892 0.892
## friends2 0.643 0.112 5.725 0.000 0.573 0.573
## family =~
## fam1 1.000 0.868 0.868
## fam2 0.961 0.068 14.078 0.000 0.834 0.834
## fam3 0.766 0.060 12.834 0.000 0.665 0.665
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school ~~
## self 0.113 0.033 3.406 0.001 0.283 0.283
## friends 0.172 0.037 4.670 0.000 0.343 0.343
## family 0.209 0.039 5.309 0.000 0.426 0.426
## self ~~
## friends 0.375 0.050 7.517 0.000 0.594 0.594
## family 0.244 0.048 5.085 0.000 0.397 0.397
## friends ~~
## family 0.300 0.048 6.319 0.000 0.388 0.388
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .school1 0.000 0.000 0.000
## .school2 0.000 0.000 0.000
## .school3 0.000 0.000 0.000
## .self1 0.000 0.000 0.000
## .self2 0.000 0.000 0.000
## .friends1 0.000 0.000 0.000
## .friends2 0.000 0.000 0.000
## .fam1 0.000 0.000 0.000
## .fam2 0.000 0.000 0.000
## .fam3 0.000 0.000 0.000
## school 0.000 0.000 0.000
## self 0.000 0.000 0.000
## friends 0.000 0.000 0.000
## family 0.000 0.000 0.000
##
## Thresholds:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school1|t1 -0.922 0.089 -10.402 0.000 -0.922 -0.922
## school1|t2 -0.358 0.078 -4.625 0.000 -0.358 -0.358
## school1|t3 0.468 0.079 5.935 0.000 0.468 0.468
## school1|t4 1.405 0.110 12.745 0.000 1.405 1.405
## school2|t1 -1.157 0.097 -11.886 0.000 -1.157 -1.157
## school2|t2 -0.398 0.078 -5.102 0.000 -0.398 -0.398
## school2|t3 0.561 0.080 6.998 0.000 0.561 0.561
## school2|t4 1.430 0.112 12.791 0.000 1.430 1.430
## school3|t1 -0.803 0.085 -9.417 0.000 -0.803 -0.803
## school3|t2 -0.114 0.076 -1.505 0.132 -0.114 -0.114
## school3|t3 0.791 0.085 9.305 0.000 0.791 0.791
## school3|t4 1.795 0.142 12.652 0.000 1.795 1.795
## self1|t1 -1.251 0.102 -12.299 0.000 -1.251 -1.251
## self1|t2 -0.706 0.083 -8.510 0.000 -0.706 -0.706
## self1|t3 0.005 0.076 0.060 0.952 0.005 0.005
## self1|t4 1.157 0.097 11.886 0.000 1.157 1.157
## self2|t1 -1.795 0.142 -12.652 0.000 -1.795 -1.795
## self2|t2 -1.231 0.101 -12.221 0.000 -1.231 -1.231
## self2|t3 -0.378 0.078 -4.864 0.000 -0.378 -0.378
## self2|t4 0.778 0.085 9.193 0.000 0.778 0.778
## friends1|t1 -1.952 0.160 -12.174 0.000 -1.952 -1.952
## friends1|t2 -1.335 0.106 -12.578 0.000 -1.335 -1.335
## friends1|t3 -0.188 0.076 -2.467 0.014 -0.188 -0.188
## friends1|t4 0.951 0.090 10.614 0.000 0.951 0.951
## friends2|t1 -2.684 0.334 -8.029 0.000 -2.684 -2.684
## friends2|t2 -1.894 0.153 -12.375 0.000 -1.894 -1.894
## friends2|t3 -0.951 0.090 -10.614 0.000 -0.951 -0.951
## friends2|t4 0.151 0.076 1.986 0.047 0.151 0.151
## fam1|t1 -1.570 0.122 -12.911 0.000 -1.570 -1.570
## fam1|t2 -1.157 0.097 -11.886 0.000 -1.157 -1.157
## fam1|t3 -0.540 0.080 -6.763 0.000 -0.540 -0.540
## fam1|t4 0.349 0.077 4.505 0.000 0.349 0.349
## fam2|t1 -1.710 0.133 -12.812 0.000 -1.710 -1.710
## fam2|t2 -1.072 0.094 -11.423 0.000 -1.072 -1.072
## fam2|t3 -0.378 0.078 -4.864 0.000 -0.378 -0.378
## fam2|t4 0.730 0.084 8.739 0.000 0.730 0.730
## fam3|t1 -1.842 0.147 -12.531 0.000 -1.842 -1.842
## fam3|t2 -1.251 0.102 -12.299 0.000 -1.251 -1.251
## fam3|t3 -0.519 0.080 -6.527 0.000 -0.519 -0.519
## fam3|t4 0.583 0.081 7.233 0.000 0.583 0.583
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .school1 0.682 0.682 0.682
## .school2 0.603 0.603 0.603
## .school3 0.241 0.241 0.241
## .self1 0.500 0.500 0.500
## .self2 0.272 0.272 0.272
## .friends1 0.205 0.205 0.205
## .friends2 0.671 0.671 0.671
## .fam1 0.246 0.246 0.246
## .fam2 0.304 0.304 0.304
## .fam3 0.557 0.557 0.557
## school 0.318 0.062 5.132 0.000 1.000 1.000
## self 0.500 0.066 7.574 0.000 1.000 1.000
## friends 0.795 0.136 5.838 0.000 1.000 1.000
## family 0.754 0.065 11.522 0.000 1.000 1.000
##
## Scales y*:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school1 1.000 1.000 1.000
## school2 1.000 1.000 1.000
## school3 1.000 1.000 1.000
## self1 1.000 1.000 1.000
## self2 1.000 1.000 1.000
## friends1 1.000 1.000 1.000
## friends2 1.000 1.000 1.000
## fam1 1.000 1.000 1.000
## fam2 1.000 1.000 1.000
## fam3 1.000 1.000 1.000
semPaths(fit_mod4f_ordered, "std")
13.1.5 Life satisfaction CFA with three factors
Model definition
Since a prior PCA suggested that 3 factors might be enough we would like to check this model using a CFA approach. Thus, we define an additional model with only three factors (friends and self factors are combined). (Ideally, the PCA should not have been carried out on the same data.)
<- "
model_3f school =~ school1 + school2 + school3
self_friends =~ self1 + self2 + friends1 + friends2
family =~ fam1 + fam2 + fam3
"
Model estimation
<- cfa(model_3f,
fit_mod3f data = lifesat,
estimator = "MLM")
summary(fit_mod3f, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 40 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 23
##
## Number of observations 275
##
## Model Test User Model:
## Standard Robust
## Test Statistic 108.940 70.324
## Degrees of freedom 32 32
## P-value (Chi-square) 0.000 0.000
## Scaling correction factor 1.549
## Satorra-Bentler correction
##
## Model Test Baseline Model:
##
## Test statistic 725.606 420.551
## Degrees of freedom 45 45
## P-value 0.000 0.000
## Scaling correction factor 1.725
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.887 0.898
## Tucker-Lewis Index (TLI) 0.841 0.856
##
## Robust Comparative Fit Index (CFI) 0.908
## Robust Tucker-Lewis Index (TLI) 0.871
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4085.347 -4085.347
## Loglikelihood unrestricted model (H1) -4030.877 -4030.877
##
## Akaike (AIC) 8216.694 8216.694
## Bayesian (BIC) 8299.880 8299.880
## Sample-size adjusted Bayesian (BIC) 8226.951 8226.951
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.094 0.066
## 90 Percent confidence interval - lower 0.075 0.049
## 90 Percent confidence interval - upper 0.113 0.083
## P-value RMSEA <= 0.05 0.000 0.058
##
## Robust RMSEA 0.082
## 90 Percent confidence interval - lower 0.056
## 90 Percent confidence interval - upper 0.108
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.071 0.071
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Structured
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school =~
## school1 1.000 0.645 0.451
## school2 1.304 0.275 4.735 0.000 0.841 0.636
## school3 1.769 0.347 5.099 0.000 1.140 0.813
## self_friends =~
## self1 1.000 0.901 0.683
## self2 0.949 0.135 7.051 0.000 0.854 0.751
## friends1 0.600 0.149 4.031 0.000 0.540 0.530
## friends2 0.331 0.085 3.877 0.000 0.298 0.367
## family =~
## fam1 1.000 1.021 0.772
## fam2 1.041 0.150 6.958 0.000 1.063 0.867
## fam3 0.630 0.118 5.355 0.000 0.643 0.575
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school ~~
## self_friends 0.177 0.065 2.718 0.007 0.304 0.304
## family 0.257 0.074 3.493 0.000 0.390 0.390
## self_friends ~~
## family 0.403 0.125 3.232 0.001 0.438 0.438
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .school1 1.627 0.175 9.270 0.000 1.627 0.796
## .school2 1.041 0.207 5.032 0.000 1.041 0.595
## .school3 0.669 0.270 2.479 0.013 0.669 0.340
## .self1 0.928 0.165 5.634 0.000 0.928 0.534
## .self2 0.564 0.160 3.527 0.000 0.564 0.436
## .friends1 0.748 0.110 6.771 0.000 0.748 0.719
## .friends2 0.572 0.056 10.142 0.000 0.572 0.866
## .fam1 0.706 0.153 4.619 0.000 0.706 0.404
## .fam2 0.373 0.121 3.069 0.002 0.373 0.248
## .fam3 0.838 0.120 6.961 0.000 0.838 0.669
## school 0.416 0.123 3.385 0.001 1.000 1.000
## self_friends 0.811 0.200 4.052 0.000 1.000 1.000
## family 1.043 0.231 4.508 0.000 1.000 1.000
Global model fit
CFI = 0.908 and NNFI/TLI = 0.871 do not reach the recommended cut-off criteria. The RMSEA = 0.082 now is also significantly greater than 0.05 (90 %-CI [0.056; 0.108]).
Optional: Alternative definition of the 3-factor model
A 3-factor model can alternatively be specified by restricting certain parameters of the 4-factor model. This allows us to show that the 3-factor model is nested in the 4-factor model.
To turn the 4-factor model into a 3-factor model with a combined self-and-friends-factor, we have to make sure that the factors friends
and self
behave like a single factor using parameter restrictions.
For these two factors to become one, the covariance between the two factors must be set to 1
(see syntax below). For a covariance of 1
to really represent an exact equality of the two factors, the variances of the two latent variables must also be set to 1 (thus the correlation between the latent variables becomes 1
). The easiest way to achieve this is to set the variances of all latent variables to the value 1 using the cfa()
argument std.lv = TRUE
, which at the same time ensures that the loadings of the first manifest variables of each factor are estimated freely. This aspect of the model is not defined in the model definition, but in the model estimation.
On the other hand, the relationships of the factors with all other factors must be identical for both factors (friends
and self)
.
We can achieve this by naming (i.e. explicitly specifying) the parameters of the factor covariances and at the same time giving the same name to parameters to be equated. For example, the covariance of friends
and school
should be estimated exactly the same as the covariance between self
and school
. If we name both parameters with a
, lavaan
recognizes that the same value should be estimated for both covariances.
We call this model model_4f_res
.
<- "
model_4f_res school =~ school1 + school2 + school3
self =~ self1 + self2
friends =~ friends1 + friends2
family =~ fam1 + fam2 + fam3
# Fixing the covariance to 1
friends ~~ 1*self
# Equality constraints: Covariances with equal parameter names
friends ~~ a*school
self ~~ a*school
friends ~~ b*family
self ~~ b*family
"
Estimating the alternative 3-factor model:
<- cfa(model_4f_res,
fit_mod4f_res std.lv = TRUE,
data = lifesat,
estimator = "MLM")
semPaths(fit_mod4f_res, "std")
Model comparison of the 3-factor model and the alternative 3-factor model
A model comparison should now show that the 3-factor model and the restricted 4-factor model do have the same model fit, i.e. are identical:
anova(fit_mod3f, fit_mod4f_res)
## Warning in lavTestLRT(object = object, ..., model.names = NAMES): lavaan
## WARNING: some models have the same degrees of freedom
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_mod3f 32 8216.7 8299.9 108.94
## fit_mod4f_res 32 8216.7 8299.9 108.94 7.4448e-10 0
Exactly! (The very small number at Chisq diff
is caused by minimal numerical inaccuracies in the ML estimation.)
Model comparison of the 3-factor model and the 4-factor model
Now we want to test the 3-factor model against the original 4-factor model.
This test examines whether the null hypothesis that the 3-factor model does not fit worse to the data than the 4-factor model has to be rejected.
anova(fit_mod3f, fit_mod4f)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_mod4f 29 8182.0 8276.0 68.21
## fit_mod3f 32 8216.7 8299.9 108.94 16.324 3 0.000973 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
The comparison is significant. The 3-factor model therefore fits the data significantly worse than the 4-factor model.
For the AIC, a value of 8181.964 was obtained for the 4-factor model and a value of 8216.694 for the 3-factor model. Thus, the 4-factor model should be preferred (smaller AIC).
A similar picture emerges for the BIC: BIC = 8276 for the 4-factor model and BIC = 8299.88 for the 3-factor model. Thus, even according to the more parsimonious BIC (favors models with fewer parameters as compared to the AIC), the 4-factor model should be selected.
13.1.6 Model with a second order factor
As we can see, the factors in the 4-factor model are all positively correlated (and significantly so). This and the fact that life satisfaction in psychological research is conceptualized not only domain-specifically, but also (and even predominantly) globally, suggests that a 2nd order factor life satisfaction might exist. In other words: general life satisfaction factor might explain the inter-correlations among the domain-specific (first order) life satisfaction factors.
In CFA we can model such a second order factor. Another factor seems to make the model more complicated at first, but this can be misleading: In fact, in a model with one second order factor, there are two parameters less to be estimated than in a model with only four first order factors: Instead of six covariances among the factors, now four loadings (or three loadings and one second order factor variance) have to be estimated.
Model definition
<- "
model_4f_2order school =~ school1 + school2 + school3
self =~ self1 + self2
friends =~ friends1 + friends2
family =~ fam1 + fam2 + fam3
# Second order factor life_satisfaction
life_satisfaction =~ school + self + friends + family
"
Model estimation
<- cfa(model_4f_2order,
fit_mod4f_2order data = lifesat,
estimator = "MLM")
semPaths(fit_mod4f_2order, "std")
summary(fit_mod4f_2order, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 54 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 24
##
## Number of observations 275
##
## Model Test User Model:
## Standard Robust
## Test Statistic 73.985 50.860
## Degrees of freedom 31 31
## P-value (Chi-square) 0.000 0.014
## Scaling correction factor 1.455
## Satorra-Bentler correction
##
## Model Test Baseline Model:
##
## Test statistic 725.606 420.551
## Degrees of freedom 45 45
## P-value 0.000 0.000
## Scaling correction factor 1.725
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.937 0.947
## Tucker-Lewis Index (TLI) 0.908 0.923
##
## Robust Comparative Fit Index (CFI) 0.955
## Robust Tucker-Lewis Index (TLI) 0.935
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4067.870 -4067.870
## Loglikelihood unrestricted model (H1) -4030.877 -4030.877
##
## Akaike (AIC) 8183.739 8183.739
## Bayesian (BIC) 8270.542 8270.542
## Sample-size adjusted Bayesian (BIC) 8194.442 8194.442
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.071 0.048
## 90 Percent confidence interval - lower 0.050 0.027
## 90 Percent confidence interval - upper 0.092 0.068
## P-value RMSEA <= 0.05 0.048 0.534
##
## Robust RMSEA 0.058
## 90 Percent confidence interval - lower 0.027
## 90 Percent confidence interval - upper 0.086
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.067 0.067
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Structured
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## school =~
## school1 1.000 0.612 0.428
## school2 1.321 0.279 4.740 0.000 0.808 0.611
## school3 1.964 0.393 4.994 0.000 1.202 0.856
## self =~
## self1 1.000 0.978 0.741
## self2 0.886 0.147 6.022 0.000 0.866 0.761
## friends =~
## friends1 1.000 0.894 0.877
## friends2 0.445 0.155 2.869 0.004 0.398 0.490
## family =~
## fam1 1.000 1.014 0.767
## fam2 1.060 0.151 7.029 0.000 1.075 0.877
## fam3 0.628 0.115 5.444 0.000 0.637 0.569
## life_satisfaction =~
## school 1.000 0.480 0.480
## self 2.255 0.734 3.072 0.002 0.678 0.678
## friends 2.049 0.708 2.892 0.004 0.674 0.674
## family 2.011 0.680 2.959 0.003 0.583 0.583
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .school1 1.668 0.176 9.486 0.000 1.668 0.817
## .school2 1.094 0.204 5.358 0.000 1.094 0.626
## .school3 0.525 0.287 1.827 0.068 0.525 0.267
## .self1 0.783 0.180 4.345 0.000 0.783 0.450
## .self2 0.544 0.164 3.312 0.001 0.544 0.420
## .friends1 0.241 0.231 1.042 0.297 0.241 0.232
## .friends2 0.502 0.062 8.075 0.000 0.502 0.760
## .fam1 0.721 0.154 4.675 0.000 0.721 0.412
## .fam2 0.347 0.120 2.897 0.004 0.347 0.231
## .fam3 0.846 0.122 6.912 0.000 0.846 0.676
## .school 0.288 0.087 3.307 0.001 0.769 0.769
## .self 0.517 0.208 2.487 0.013 0.541 0.541
## .friends 0.436 0.240 1.816 0.069 0.546 0.546
## .family 0.679 0.182 3.725 0.000 0.660 0.660
## life_satisfctn 0.086 0.047 1.856 0.064 1.000 1.000
The parameter estimates show that the strongest standardized loadings of the domain-specific (first order) factors are those of the self and of the friends factors, while the lowest is that of the school factor.
Model fit and model comparisons
Robust CFI = 0.955 and NNFI/TLI = 0.935 are very similar to the respective indices of the 4-factor model. The RMSEA = 0.058 is slightly lower than with the 4-factor model and not significantly greater than 0.05 (90 %-CI [0.027; 0.086]).
Now we compare all three models (in ascending order with regard to the number of estimated parameters: 3-factor model, 4-factor model with second-order factor, 4-factor model) using sequential likelihood-ratio tests. The prerequisite for the validity of these tests is the nesting of restricted models (with fewer parameters) in models with fewer restrictions (with more parameters). For the 3-factor and the 4-factor models we have demonstrated the nesting above. But also the 4-factor model with a second-order factor is nested in the 4-factor model (because actually all models that have the same four first order factors are nested in this model since it is a saturated model at the level of latent variables).
anova(fit_mod3f, fit_mod4f_2order, fit_mod4f)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_mod4f 29 8182.0 8276.0 68.210
## fit_mod4f_2order 31 8183.7 8270.5 73.985 3.8396 2 0.146639
## fit_mod3f 32 8216.7 8299.9 108.940 7.8078 1 0.005202 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
The model comparison shows that the 4-factor model with a 2nd-order factor does not fit the data significantly worse than the less parsimonious 4-factor model (\(\Delta\chi^2=\) 3.8396, \(p =\) 0.1466). The second test, on the other hand, shows a significant model comparison of the 3-factor model with the 4-factor model with a second-order factor (\(\Delta\chi^2=\) 7.8078, \(p =\) 0.0052).
The best of these three models is therefore the 4-factor model with a 2nd-order factor. With regard to information criteria this model also has the lowest Bayesian Information Criterion (BIC = 8270.5 while the model with lowest Akaike Information Criterion (favoring less parsimonious models with more parameters) is the original 4-factor model (AIC = 8183.7).
13.2 Structural Equation Modelling (SEM)
13.2.1 Introduction
SEM represents a combination of CFA with regression models and allows to model complex regression structures (path models) at the level of latent variables. Indirect effects (mediation models) can also be estimated. The estimation theory does not differ from that of CFA.
As an example we will study the effects of emotional support by parents and friends as experienced by adolescents on their life satisfaction. The two self-efficacy domains “academic self-efficacy” and “social self-efficacy” will serve as mediators for these effects. Both direct and indirect effects will be investigated.
Theoretical basis and hypotheses: Both parental support and support from friends have a positive effect on life satisfaction. In addition, it is known from self-efficacy research that experienced support can have positive effects on the experience of self-efficacy, and that this experience in turn is related to higher life satisfaction. An important question, however, concerns the differential effects resulting when these constructs with their respective domains are considered simultaneously.
The assumed effects can be summarized in the following structural model:
For the postulated structural model (relations between the latent variables) we need a measurement model (relations between the latent variables and the manifest variables, i.e. the factor structure). With a large number of measured variables the measurement model is often based on “packages” of individual items rather than on the individual items themselves. Here we choose the “item-to-construct balance approach” to packaging (Little et al., 2002), in which individual items representing a certain construct are combined in such a way that the “packed” manifest variables load as homogeneously as possible on the respective latent factor. It is generally recommended to use three to four parcels per latent variable.
The following parcels were built:
Emotional support from parents (6 items): 3 parcels of 2 items (sup_parents_p1, sup_parents_p2, sup_parents_p3)
Emotional support from friends (6 items): 3 parcels of 2 items (sup_friends_p1, sup_friends_p2, sup_friends_p3)
Academic self-efficacy (20 items): 2 parcels of 7 items & 1 parcel of 6 items (se_acad_p1, se_acad_p2, se_acad_p3)
Social self-efficacy (16 items): 2 parcels of 5 items & 1 parcel of 6 items (se_social_p1, se_social_p2, se_social_p3)
Life satisfaction (11 items): 2 parcels of 4 items & 1 parcel of 3 items (ls_p1, ls_p2, ls_p3)
The SEM analysis is carried out in three steps:
We start with the measurement model. The measurement model is a multi-construct CFA with intercorrelations of all latent variables.
Then we consider the entire structural equation model (measurement and structural model combined).
In the last step we will show how to explicitly define indirect and total effects within the SEM.
13.2.2 Importing the data
<- read_csv(
data_sem url("https://raw.githubusercontent.com/methodenlehre/data/master/sem_data.csv"))
## Rows: 283 Columns: 19
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): region, gender
## dbl (17): ID, age, se_acad_p1, se_acad_p2, se_acad_p3, se_social_p1, se_soci...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# convert ID and gender to factors
$ID <- as.factor(data_sem$ID)
data_sem$region <- as.factor(data_sem$region)
data_sem$gender <- as.factor(data_sem$gender) data_sem
13.2.3 Measurement model
In the measurement model, the relationships between the latent variables (factors) and the manifest variables are defined. We are already familiar with the lavaan
model definition from the CFA example above.
Error variances of the observed variables and variances of the exogenous latent variables do not have to be explicitly specified.
Operator for the measuring model:
=~
(“is measured by…”)
<- "
model_measurement # 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
"
Model estimation
The function sem()
is applied to the model_measurement
specified above, and the results are stored in an object (here fit_measurement
). We could also use cfa()
here. The two functions differ only slightly in their default settings and are both equally suitable for estimating measurement models.
Let’s have a look at univariate and multivariate normality of the data:
# univariate skewness and kurtosis
<- data_sem[-(1:4)] %>%
check_sem describe()
$skew check_sem
## [1] -0.2629296 -0.3354220 -0.2959812 -0.5640013 -0.6063687 -0.4473382
## [7] -1.2294259 -1.2473578 -1.5262892 -1.4238442 -1.1944909 -1.2408782
## [13] -0.7683010 -1.2142986 -0.6984612
$kurtosis check_sem
## [1] -0.4082208 -0.2082133 -0.1383948 1.4428096 0.7746075 -0.1695429
## [7] 1.8438486 1.6086578 2.7745329 2.6667347 1.1928812 1.7737603
## [13] 0.7185157 2.8794007 0.5447682
# multivariate skewness and kurtosis
-(1:4)] %>%
data_sem[mardiaSkew()
## b1d chi df p
## 4.617123e+01 2.177743e+03 6.800000e+02 4.263531e-156
-(1:4)] %>%
data_sem[mardiaKurtosis()
## b2d z p
## 3.328664e+02 2.900204e+01 6.201873e-185
<- sem(model_measurement,
fit_measurement data = data_sem,
estimator = "MLM")
summary(fit_measurement, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 49 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 40
##
## Number of observations 283
##
## Model Test User Model:
## Standard Robust
## Test Statistic 223.992 183.847
## Degrees of freedom 80 80
## P-value (Chi-square) 0.000 0.000
## Scaling correction factor 1.218
## Satorra-Bentler correction
##
## Model Test Baseline Model:
##
## Test statistic 2696.489 1983.449
## Degrees of freedom 105 105
## P-value 0.000 0.000
## Scaling correction factor 1.359
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.944 0.945
## Tucker-Lewis Index (TLI) 0.927 0.927
##
## Robust Comparative Fit Index (CFI) 0.950
## Robust Tucker-Lewis Index (TLI) 0.935
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4285.972 -4285.972
## Loglikelihood unrestricted model (H1) -4173.976 -4173.976
##
## Akaike (AIC) 8651.944 8651.944
## Bayesian (BIC) 8797.761 8797.761
## Sample-size adjusted Bayesian (BIC) 8670.921 8670.921
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.080 0.068
## 90 Percent confidence interval - lower 0.067 0.056
## 90 Percent confidence interval - upper 0.092 0.079
## P-value RMSEA <= 0.05 0.000 0.007
##
## Robust RMSEA 0.075
## 90 Percent confidence interval - lower 0.061
## 90 Percent confidence interval - upper 0.089
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.056 0.056
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Structured
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sup_parents_p1 1.000 0.935 0.873
## sup_parents_p2 1.036 0.061 16.969 0.000 0.969 0.887
## sup_parents_p3 0.996 0.070 14.274 0.000 0.932 0.816
## SUP_Friends =~
## sup_friends_p1 1.000 1.021 0.906
## sup_friends_p2 0.792 0.061 12.917 0.000 0.809 0.857
## sup_friends_p3 0.891 0.077 11.631 0.000 0.910 0.831
## SE_Academic =~
## se_acad_p1 1.000 0.695 0.878
## se_acad_p2 0.809 0.045 17.983 0.000 0.562 0.820
## se_acad_p3 0.955 0.057 16.681 0.000 0.664 0.829
## SE_Social =~
## se_social_p1 1.000 0.638 0.843
## se_social_p2 0.967 0.065 14.840 0.000 0.617 0.885
## se_social_p3 0.928 0.066 13.974 0.000 0.592 0.741
## LS =~
## ls_p1 1.000 0.667 0.718
## ls_p2 0.778 0.075 10.411 0.000 0.519 0.712
## ls_p3 0.968 0.086 11.272 0.000 0.645 0.732
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents ~~
## SUP_Friends 0.132 0.066 2.012 0.044 0.138 0.138
## SE_Academic 0.218 0.043 5.071 0.000 0.336 0.336
## SE_Social 0.282 0.063 4.457 0.000 0.472 0.472
## LS 0.405 0.065 6.275 0.000 0.650 0.650
## SUP_Friends ~~
## SE_Academic 0.071 0.044 1.611 0.107 0.100 0.100
## SE_Social 0.196 0.039 5.057 0.000 0.301 0.301
## LS 0.175 0.050 3.482 0.000 0.257 0.257
## SE_Academic ~~
## SE_Social 0.271 0.035 7.665 0.000 0.611 0.611
## LS 0.238 0.043 5.496 0.000 0.514 0.514
## SE_Social ~~
## LS 0.321 0.053 6.004 0.000 0.755 0.755
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.273 0.043 6.355 0.000 0.273 0.238
## .sup_parents_p2 0.255 0.054 4.717 0.000 0.255 0.213
## .sup_parents_p3 0.437 0.070 6.280 0.000 0.437 0.335
## .sup_friends_p1 0.227 0.071 3.186 0.001 0.227 0.179
## .sup_friends_p2 0.238 0.054 4.408 0.000 0.238 0.266
## .sup_friends_p3 0.371 0.097 3.832 0.000 0.371 0.310
## .se_acad_p1 0.144 0.028 5.149 0.000 0.144 0.229
## .se_acad_p2 0.153 0.020 7.629 0.000 0.153 0.327
## .se_acad_p3 0.200 0.031 6.547 0.000 0.200 0.313
## .se_social_p1 0.166 0.023 7.060 0.000 0.166 0.290
## .se_social_p2 0.106 0.017 6.150 0.000 0.106 0.217
## .se_social_p3 0.288 0.028 10.373 0.000 0.288 0.451
## .ls_p1 0.417 0.048 8.643 0.000 0.417 0.484
## .ls_p2 0.261 0.057 4.568 0.000 0.261 0.492
## .ls_p3 0.362 0.046 7.942 0.000 0.362 0.465
## SUP_Parents 0.875 0.147 5.958 0.000 1.000 1.000
## SUP_Friends 1.042 0.148 7.025 0.000 1.000 1.000
## SE_Academic 0.483 0.049 9.919 0.000 1.000 1.000
## SE_Social 0.407 0.062 6.518 0.000 1.000 1.000
## LS 0.444 0.076 5.826 0.000 1.000 1.000
As can be seen from the output the standardized loadings are all relatively high and also homogeneous. The factor correlations of this multi-construct measurement model are between \(r = 0.100\) (SUP_Friends
\(\leftrightarrow\) SE_Academic
) and \(r = 0.755\) (SE_Social
\(\leftrightarrow\) LS
).
Global model fit is not really good (CFI = 0.95, NNFI/TLI = 0.935, RMSEA = 0.075, 90 %-CI: [0.061; 0.089]) but can still be seen as acceptable according to commonly accepted criteria.
In order to determine where problems exist in the model fit, we can first consider the standardized residual variance-covariance matrix:
resid(fit_measurement, type = "standardized")$cov
## sp_p_1 sp_p_2 sp_p_3 sp_f_1 sp_f_2 sp_f_3 s_cd_1 s_cd_2 s_cd_3
## sup_parents_p1 0.000
## sup_parents_p2 2.434 0.000
## sup_parents_p3 -1.429 -1.067 0.000
## sup_friends_p1 0.866 1.006 -3.755 0.000
## sup_friends_p2 1.269 1.365 -1.737 0.872 0.000
## sup_friends_p3 0.636 1.022 -2.149 0.695 -1.351 0.000
## se_acad_p1 -0.622 -1.488 2.267 -0.629 0.066 0.719 0.000
## se_acad_p2 -0.561 -0.644 1.500 0.636 0.925 0.464 -0.776 0.000
## se_acad_p3 -0.724 -0.930 2.396 -1.726 0.299 -0.128 0.421 0.250 0.000
## se_social_p1 1.369 0.658 2.131 -3.995 -1.830 -1.750 3.100 0.822 1.063
## se_social_p2 -0.168 -0.606 -0.251 1.021 1.738 1.662 -1.766 -0.652 -2.323
## se_social_p3 -1.332 -1.108 -0.929 2.452 0.429 1.255 -0.144 1.448 -0.624
## ls_p1 -2.573 -3.037 0.431 -3.825 -1.256 -1.387 -0.667 2.059 1.091
## ls_p2 -1.485 -2.864 -0.651 2.180 4.373 3.112 -2.427 -1.568 -2.791
## ls_p3 2.056 3.067 4.537 -1.555 -0.217 -0.289 1.661 1.410 1.896
## s_sc_1 s_sc_2 s_sc_3 ls_p1 ls_p2 ls_p3
## sup_parents_p1
## sup_parents_p2
## sup_parents_p3
## sup_friends_p1
## sup_friends_p2
## sup_friends_p3
## se_acad_p1
## se_acad_p2
## se_acad_p3
## se_social_p1 0.000
## se_social_p2 0.786 0.000
## se_social_p3 -2.264 1.130 0.000
## ls_p1 -0.391 -0.899 -0.384 0.000
## ls_p2 2.483 1.884 2.431 2.206 0.000
## ls_p3 -1.080 -2.168 -1.795 0.956 -3.811 0.000
This shows that the variance-covariance matrix implied by the model deviates significantly from the empirical variance-covariance matrix for a number of covariances, e.g. for sp_p_3 ~~ ls_p3
or for sp_f_2 ~~ ls_p2
.
Modification indices
Another possibility for local fit diagnostics is offered by modification indices. These indicate which additional model parameters would result in a significant fit improvement (in terms of a reduction of \(\chi^2\) by the value of the corresponding MI). We will only display the MI \(\geq 5\), since usually only those are considered substantial.
modindices(fit_measurement, standardized = FALSE, minimum.value = 5)
## lhs op rhs mi epc
## 55 SUP_Parents =~ ls_p1 8.480 -0.237
## 56 SUP_Parents =~ ls_p2 6.169 -0.158
## 57 SUP_Parents =~ ls_p3 28.086 0.411
## 60 SUP_Friends =~ sup_parents_p3 16.443 -0.189
## 64 SUP_Friends =~ se_social_p1 16.789 -0.134
## 65 SUP_Friends =~ se_social_p2 5.289 0.069
## 67 SUP_Friends =~ ls_p1 6.881 -0.133
## 68 SUP_Friends =~ ls_p2 15.119 0.155
## 72 SE_Academic =~ sup_parents_p3 8.733 0.218
## 76 SE_Academic =~ se_social_p1 9.991 0.206
## 77 SE_Academic =~ se_social_p2 9.885 -0.190
## 80 SE_Academic =~ ls_p2 11.947 -0.247
## 81 SE_Academic =~ ls_p3 5.984 0.212
## 92 SE_Social =~ ls_p2 12.281 0.440
## 93 SE_Social =~ ls_p3 6.535 -0.393
## 96 LS =~ sup_parents_p3 6.743 0.286
## 106 sup_parents_p1 ~~ sup_parents_p2 9.237 0.196
## 133 sup_parents_p3 ~~ sup_friends_p1 9.338 -0.084
## 144 sup_parents_p3 ~~ ls_p3 9.302 0.090
## 150 sup_friends_p1 ~~ se_social_p1 8.932 -0.053
## 152 sup_friends_p1 ~~ se_social_p3 18.792 0.094
## 162 sup_friends_p2 ~~ se_social_p3 8.353 -0.056
## 164 sup_friends_p2 ~~ ls_p2 5.784 0.046
## 177 se_acad_p1 ~~ se_social_p1 12.065 0.047
## 180 se_acad_p1 ~~ ls_p1 6.839 -0.053
## 187 se_acad_p2 ~~ ls_p1 5.411 0.044
## 194 se_acad_p3 ~~ ls_p2 5.268 -0.040
## 197 se_social_p1 ~~ se_social_p3 5.022 -0.046
## 206 se_social_p3 ~~ ls_p2 9.322 0.059
## 208 ls_p1 ~~ ls_p2 7.056 0.079
## 210 ls_p2 ~~ ls_p3 13.346 -0.105
A total of 31 modification indices are displayed. They refer either to possible cross-loadings (e.g. SUP_Parents =~ ls_p3
: MI = 28.086) or to residual covariances between manifest variables (e.g. sup_friends_p1 ~~ se_social_p3
: MI = 18.792). For theoretical reasons it is not recommended to add cross-loadings or residual covariances (especially across different latent variables) to the model.
Such model fit problems often arise in self-report studies. Individual differences in scale use (response styles) can play a role: These can lead to generally increased correlations among the variables, which may not be adequately taken into account in a multi-construct measurement model. There are approaches (definition of method and response style factors) to deal with this issue.
Another reason for the model-fit problems in this study could be the general similarity of the constructs investigated with respect to life domains. For example, there are life satisfaction items with respect to friends, but the friends context also plays an important role for the items for social self-efficacy and, of course, for support received from friends.
Since the model fit is still acceptable, we continue to work with this measurement model. In the next step we will model the effects among latent variables in order to test our theoretical assumptions (structural model).
13.2.4 Structural model
Model definition
The structural model represents the relationships/effects among the latent variables. It is added to the measurement model definitions:
<- "
model # 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 ~ SUP_Parents + SUP_Friends
SE_Social ~ SUP_Parents + SUP_Friends
LS ~ SE_Academic + SE_Social + SUP_Parents + SUP_Friends
# Residual covariances
SE_Academic ~~ SE_Social
"
Operator for the structural model (regressions of latent variables):
~
(“is predicted by…”)Operator for (residual) variances and covariances:
~~
(for variances, the same variable appears on the left and right; for covariances, different variables). As in the measurement model (CFA), variances and covariances of exogenous latent variables do not have to be specified (are automatically estimated). The residual variances of endogenous latent variables are also estimated automatically.
Therefore we only have to specify one parameter using ~~
: In this model we have two parallel latent mediator variables (SE_Academic
and SE_Social)
which have no effects on each other. However, it can be assumed that these two variables (or rather their residuals) co-vary since a general self-efficacy component is likely (cf. also the correlation of \(r=0.621\) in the measurement model above). Since SE_Academic
and SE_Social
are endogenous latent variables (both are predicted by both SUP_Parents
and SUP_Friends
), a residual covariance \(\psi =\) SE_Academic ~~ SE_Social
must be specified.
Model estimation
<- sem(model,
fit data = data_sem,
estimator = "MLM")
summary(fit, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 43 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 40
##
## Number of observations 283
##
## Model Test User Model:
## Standard Robust
## Test Statistic 223.992 183.847
## Degrees of freedom 80 80
## P-value (Chi-square) 0.000 0.000
## Scaling correction factor 1.218
## Satorra-Bentler correction
##
## Model Test Baseline Model:
##
## Test statistic 2696.489 1983.449
## Degrees of freedom 105 105
## P-value 0.000 0.000
## Scaling correction factor 1.359
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.944 0.945
## Tucker-Lewis Index (TLI) 0.927 0.927
##
## Robust Comparative Fit Index (CFI) 0.950
## Robust Tucker-Lewis Index (TLI) 0.935
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4285.972 -4285.972
## Loglikelihood unrestricted model (H1) -4173.976 -4173.976
##
## Akaike (AIC) 8651.944 8651.944
## Bayesian (BIC) 8797.761 8797.761
## Sample-size adjusted Bayesian (BIC) 8670.921 8670.921
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.080 0.068
## 90 Percent confidence interval - lower 0.067 0.056
## 90 Percent confidence interval - upper 0.092 0.079
## P-value RMSEA <= 0.05 0.000 0.007
##
## Robust RMSEA 0.075
## 90 Percent confidence interval - lower 0.061
## 90 Percent confidence interval - upper 0.089
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.056 0.056
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Structured
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sup_parents_p1 1.000 0.935 0.873
## sup_parents_p2 1.036 0.061 16.969 0.000 0.969 0.887
## sup_parents_p3 0.996 0.070 14.274 0.000 0.932 0.816
## SUP_Friends =~
## sup_friends_p1 1.000 1.021 0.906
## sup_friends_p2 0.792 0.061 12.917 0.000 0.809 0.857
## sup_friends_p3 0.891 0.077 11.631 0.000 0.910 0.831
## SE_Academic =~
## se_acad_p1 1.000 0.695 0.878
## se_acad_p2 0.809 0.045 17.983 0.000 0.562 0.820
## se_acad_p3 0.955 0.057 16.681 0.000 0.664 0.829
## SE_Social =~
## se_social_p1 1.000 0.638 0.843
## se_social_p2 0.967 0.065 14.840 0.000 0.617 0.885
## se_social_p3 0.928 0.066 13.974 0.000 0.592 0.741
## LS =~
## ls_p1 1.000 0.667 0.718
## ls_p2 0.778 0.075 10.411 0.000 0.519 0.712
## ls_p3 0.968 0.086 11.272 0.000 0.645 0.732
##
## Regressions:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SE_Academic ~
## SUP_Parents 0.244 0.055 4.450 0.000 0.328 0.328
## SUP_Friends 0.037 0.044 0.843 0.399 0.054 0.054
## SE_Social ~
## SUP_Parents 0.300 0.062 4.850 0.000 0.439 0.439
## SUP_Friends 0.150 0.038 3.978 0.000 0.240 0.240
## LS ~
## SE_Academic 0.058 0.078 0.745 0.457 0.061 0.061
## SE_Social 0.553 0.091 6.081 0.000 0.529 0.529
## SUP_Parents 0.267 0.049 5.424 0.000 0.375 0.375
## SUP_Friends 0.026 0.036 0.727 0.467 0.040 0.040
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .SE_Academic ~~
## .SE_Social 0.195 0.028 7.064 0.000 0.551 0.551
## SUP_Parents ~~
## SUP_Friends 0.132 0.066 2.012 0.044 0.138 0.138
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.273 0.043 6.355 0.000 0.273 0.238
## .sup_parents_p2 0.255 0.054 4.717 0.000 0.255 0.213
## .sup_parents_p3 0.437 0.070 6.280 0.000 0.437 0.335
## .sup_friends_p1 0.227 0.071 3.186 0.001 0.227 0.179
## .sup_friends_p2 0.238 0.054 4.408 0.000 0.238 0.266
## .sup_friends_p3 0.371 0.097 3.832 0.000 0.371 0.310
## .se_acad_p1 0.144 0.028 5.149 0.000 0.144 0.229
## .se_acad_p2 0.153 0.020 7.629 0.000 0.153 0.327
## .se_acad_p3 0.200 0.031 6.547 0.000 0.200 0.313
## .se_social_p1 0.166 0.023 7.060 0.000 0.166 0.290
## .se_social_p2 0.106 0.017 6.150 0.000 0.106 0.217
## .se_social_p3 0.288 0.028 10.373 0.000 0.288 0.451
## .ls_p1 0.417 0.048 8.643 0.000 0.417 0.484
## .ls_p2 0.261 0.057 4.568 0.000 0.261 0.492
## .ls_p3 0.362 0.046 7.942 0.000 0.362 0.465
## SUP_Parents 0.875 0.147 5.958 0.000 1.000 1.000
## SUP_Friends 1.042 0.148 7.025 0.000 1.000 1.000
## .SE_Academic 0.427 0.043 9.863 0.000 0.884 0.884
## .SE_Social 0.293 0.041 7.200 0.000 0.720 0.720
## .LS 0.140 0.033 4.277 0.000 0.315 0.315
The model fit is exactly the same! We have already seen above that we have just as many parameters and degrees of freedom in the overall model as in the measurement model.
This means that the structural model is saturated!
In the measurement model we had 15 variance and covariance parameters of the latent variables, so the variance-covariance matrix of the latent variables (with 5 x 6/2 = 15 elements) was complete and unrestricted. We now also have 15 parameters in the structural model. The parameters of the structural model are estimable and we can thus test our postulated effects, but this part of the overall model is just identified (since \(n_{Info} = n_{Par}\) with regard to the latent variables) and thus does not contribute to the model fit of the overall model! In other words: We cannot check whether the structural model fits our data well, only the fit of the measurement model can be tested.
Interpretation of the estimated structural coefficients:
Of the 8 postulated structural paths, 5 are significant and go in the expected direction. Not significant are the effects of SUP_Friends
on SE_Academic
(Std.all \(= 0.054,\ p = 0.399\)), from SE_Academic
to LS
(Std.all \(= 0.061,\ p = 0.457\)), and from SUP_Friends
to LS
(Std.all \(= 0.040,\ p = 0.467\)).
It is particularly striking that the perceived support by the parents has a substantial direct effect on life satisfaction, whereas the direct effect of the perceived support by the friends is not significant. It is also interesting that the academic self-efficacy no longer has a significant effect on satisfaction when social self-efficacy is held constant, even though the correlation between the two latent variables SE_Academic
and LS
was substantial in the measurement model (see above \(r = 0.514,\ p < 0.001\)).
Estimating indirect and total effects
With one or more latent mediator variables present in the structural model the SEM turns into a latent mediation analysis. To estimate indirect and total effects, the parameters of the structural model must first be explicitly named in the model definition (multiplication of predictors with b1, b2, b3, etc.).
Specific and total indirect effects can then be defined as products (or sum of products) of the path parameters (operator:
:=
)Total effects can be defined equally as the sum of indirect and direct effects
When indirect and total effects are defined the model should always be estimated using the se = "bootstrap"
option (even if the data are otherwise normally distributed). This is because other than the path coefficients themselves indirect effects (products of path coefficients) are not asymptotically normally distributed which renders the z- or Wald-approximation inappropriate for these defined parameters.
<- '
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
'
<- sem(model_mediation,
fit_mediation data = data_sem,
se = "bootstrap",
verbose = FALSE,
bootstrap = 1000)
summary(fit_mediation, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 43 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 40
##
## Number of observations 283
##
## Model Test User Model:
##
## Test statistic 223.992
## Degrees of freedom 80
## P-value (Chi-square) 0.000
##
## Model Test Baseline Model:
##
## Test statistic 2696.489
## Degrees of freedom 105
## P-value 0.000
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.944
## Tucker-Lewis Index (TLI) 0.927
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4285.972
## Loglikelihood unrestricted model (H1) -4173.976
##
## Akaike (AIC) 8651.944
## Bayesian (BIC) 8797.761
## Sample-size adjusted Bayesian (BIC) 8670.921
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.080
## 90 Percent confidence interval - lower 0.067
## 90 Percent confidence interval - upper 0.092
## P-value RMSEA <= 0.05 0.000
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.056
##
## Parameter Estimates:
##
## Standard errors Bootstrap
## Number of requested bootstrap draws 1000
## Number of successful bootstrap draws 1000
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sup_parents_p1 1.000 0.935 0.873
## sup_parents_p2 1.036 0.062 16.817 0.000 0.969 0.887
## sup_parents_p3 0.996 0.076 13.073 0.000 0.932 0.816
## SUP_Friends =~
## sup_friends_p1 1.000 1.021 0.906
## sup_friends_p2 0.792 0.061 12.913 0.000 0.809 0.857
## sup_friends_p3 0.891 0.075 11.921 0.000 0.910 0.831
## SE_Academic =~
## se_acad_p1 1.000 0.695 0.878
## se_acad_p2 0.809 0.047 17.232 0.000 0.562 0.820
## se_acad_p3 0.955 0.056 16.948 0.000 0.664 0.829
## SE_Social =~
## se_social_p1 1.000 0.638 0.843
## se_social_p2 0.967 0.068 14.174 0.000 0.617 0.885
## se_social_p3 0.928 0.078 11.937 0.000 0.592 0.741
## LS =~
## ls_p1 1.000 0.667 0.718
## ls_p2 0.778 0.090 8.604 0.000 0.519 0.712
## ls_p3 0.968 0.103 9.434 0.000 0.645 0.732
##
## Regressions:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SE_Academic ~
## SUP_Prnts (b1) 0.244 0.060 4.080 0.000 0.328 0.328
## SUP_Frnds (b3) 0.037 0.044 0.839 0.402 0.054 0.054
## SE_Social ~
## SUP_Prnts (b2) 0.300 0.063 4.776 0.000 0.439 0.439
## SUP_Frnds (b4) 0.150 0.039 3.797 0.000 0.240 0.240
## LS ~
## SUP_Prnts (b5) 0.267 0.058 4.579 0.000 0.375 0.375
## SUP_Frnds (b6) 0.026 0.042 0.634 0.526 0.040 0.040
## SE_Acadmc (b7) 0.058 0.099 0.589 0.556 0.061 0.061
## SE_Social (b8) 0.553 0.118 4.663 0.000 0.529 0.529
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .SE_Academic ~~
## .SE_Social 0.195 0.029 6.653 0.000 0.551 0.551
## SUP_Parents ~~
## SUP_Friends 0.132 0.068 1.934 0.053 0.138 0.138
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.273 0.040 6.757 0.000 0.273 0.238
## .sup_parents_p2 0.255 0.051 4.959 0.000 0.255 0.213
## .sup_parents_p3 0.437 0.071 6.151 0.000 0.437 0.335
## .sup_friends_p1 0.227 0.069 3.280 0.001 0.227 0.179
## .sup_friends_p2 0.238 0.052 4.577 0.000 0.238 0.266
## .sup_friends_p3 0.371 0.093 3.990 0.000 0.371 0.310
## .se_acad_p1 0.144 0.027 5.264 0.000 0.144 0.229
## .se_acad_p2 0.153 0.020 7.576 0.000 0.153 0.327
## .se_acad_p3 0.200 0.030 6.643 0.000 0.200 0.313
## .se_social_p1 0.166 0.024 6.815 0.000 0.166 0.290
## .se_social_p2 0.106 0.017 6.158 0.000 0.106 0.217
## .se_social_p3 0.288 0.029 10.037 0.000 0.288 0.451
## .ls_p1 0.417 0.053 7.947 0.000 0.417 0.484
## .ls_p2 0.261 0.062 4.247 0.000 0.261 0.492
## .ls_p3 0.362 0.058 6.246 0.000 0.362 0.465
## SUP_Parents 0.875 0.153 5.710 0.000 1.000 1.000
## SUP_Friends 1.042 0.151 6.884 0.000 1.000 1.000
## .SE_Academic 0.427 0.042 10.090 0.000 0.884 0.884
## .SE_Social 0.293 0.044 6.606 0.000 0.720 0.720
## .LS 0.140 0.036 3.933 0.000 0.315 0.315
##
## Defined Parameters:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## b1b7 0.014 0.025 0.560 0.576 0.020 0.020
## b2b8 0.166 0.045 3.713 0.000 0.232 0.232
## totalind_eltrn 0.180 0.041 4.372 0.000 0.252 0.252
## b3b7 0.002 0.006 0.352 0.725 0.003 0.003
## b4b8 0.083 0.029 2.879 0.004 0.127 0.127
## totalind_frend 0.085 0.028 3.025 0.002 0.130 0.130
## total_eltern 0.447 0.071 6.326 0.000 0.627 0.627
## total_freunde 0.111 0.049 2.276 0.023 0.171 0.171
13.2.5 Summary
Acceptable model fit of the measurement model
Structural model saturated, model fit not verifiable
Support by parents most important for the life satisfaction of young people
- Total effect more than twice as large compared to support from friends
- Direct effect strongest, but also substantial indirect effect via social self-efficacy
Support from friends with only an indirect effect on life satisfaction through social self-efficacy
Social self-efficacy strongest predictor of life satisfaction
Academic self-efficacy irrelevant for life satisfaction when controlling for social self-efficacy
\(~\)
Summary of the effects in the structural model:
Summary of the indirect effects:
13.3 CFA and SEM with multiple groups
13.3.1 Measurement invariance analysis across multiple groups
Configural invariance
In a first step, the model is estimated with separate parameters for the two regional groups (“west”" and “east”), i.e. with twice as many model parameters. The overall model fit thus informs about a cross-group invariance with respect to the configural structure (e.g. a factor model with a certain number of factors and certain loadings etc.).
<- sem(model_measurement,
fit_configural data = data_sem,
estimator = "MLM",
group = "region")
summary(fit_configural, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 64 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 110
##
## Number of observations per group:
## west 141
## east 142
##
## Model Test User Model:
## Standard Robust
## Test Statistic 328.778 279.542
## Degrees of freedom 160 160
## P-value (Chi-square) 0.000 0.000
## Scaling correction factor 1.176
## Satorra-Bentler correction
## Test statistic for each group:
## west 170.704 145.141
## east 158.073 134.401
##
## Model Test Baseline Model:
##
## Test statistic 2786.197 1986.569
## Degrees of freedom 210 210
## P-value 0.000 0.000
## Scaling correction factor 1.403
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.934 0.933
## Tucker-Lewis Index (TLI) 0.914 0.912
##
## Robust Comparative Fit Index (CFI) 0.944
## Robust Tucker-Lewis Index (TLI) 0.926
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4178.506 -4178.506
## Loglikelihood unrestricted model (H1) -4014.118 -4014.118
##
## Akaike (AIC) 8577.013 8577.013
## Bayesian (BIC) 8978.012 8978.012
## Sample-size adjusted Bayesian (BIC) 8629.201 8629.201
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.086 0.073
## 90 Percent confidence interval - lower 0.073 0.059
## 90 Percent confidence interval - upper 0.100 0.086
## P-value RMSEA <= 0.05 0.000 0.003
##
## Robust RMSEA 0.079
## 90 Percent confidence interval - lower 0.063
## 90 Percent confidence interval - upper 0.094
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.061 0.061
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Structured
##
##
## Group 1 [west]:
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sup_parents_p1 1.000 0.991 0.886
## sup_parents_p2 1.083 0.083 13.017 0.000 1.073 0.907
## sup_parents_p3 0.959 0.100 9.635 0.000 0.950 0.771
## SUP_Friends =~
## sup_friends_p1 1.000 1.169 0.914
## sup_friends_p2 0.794 0.082 9.660 0.000 0.929 0.844
## sup_friends_p3 0.913 0.111 8.189 0.000 1.067 0.834
## SE_Academic =~
## se_acad_p1 1.000 0.659 0.889
## se_acad_p2 0.783 0.063 12.398 0.000 0.516 0.788
## se_acad_p3 0.965 0.084 11.522 0.000 0.636 0.850
## SE_Social =~
## se_social_p1 1.000 0.615 0.845
## se_social_p2 1.027 0.095 10.795 0.000 0.632 0.854
## se_social_p3 0.884 0.109 8.107 0.000 0.544 0.707
## LS =~
## ls_p1 1.000 0.638 0.705
## ls_p2 0.777 0.119 6.503 0.000 0.496 0.682
## ls_p3 0.981 0.133 7.381 0.000 0.626 0.736
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents ~~
## SUP_Friends 0.219 0.112 1.961 0.050 0.189 0.189
## SE_Academic 0.164 0.063 2.618 0.009 0.252 0.252
## SE_Social 0.209 0.061 3.448 0.001 0.344 0.344
## LS 0.340 0.061 5.609 0.000 0.537 0.537
## SUP_Friends ~~
## SE_Academic 0.012 0.071 0.171 0.865 0.016 0.016
## SE_Social 0.189 0.058 3.267 0.001 0.262 0.262
## LS 0.182 0.079 2.305 0.021 0.244 0.244
## SE_Academic ~~
## SE_Social 0.242 0.044 5.489 0.000 0.598 0.598
## LS 0.223 0.061 3.624 0.000 0.530 0.530
## SE_Social ~~
## LS 0.284 0.068 4.212 0.000 0.725 0.725
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 5.947 0.094 63.141 0.000 5.947 5.317
## .sup_parents_p2 5.798 0.100 58.172 0.000 5.798 4.899
## .sup_parents_p3 5.574 0.104 53.734 0.000 5.574 4.525
## .sup_friends_p1 5.670 0.108 52.613 0.000 5.670 4.431
## .sup_friends_p2 5.901 0.093 63.697 0.000 5.901 5.364
## .sup_friends_p3 5.858 0.108 54.386 0.000 5.858 4.580
## .se_acad_p1 4.982 0.062 79.820 0.000 4.982 6.722
## .se_acad_p2 5.165 0.055 93.644 0.000 5.165 7.886
## .se_acad_p3 4.899 0.063 77.797 0.000 4.899 6.552
## .se_social_p1 5.216 0.061 85.032 0.000 5.216 7.161
## .se_social_p2 5.328 0.062 85.534 0.000 5.328 7.203
## .se_social_p3 5.273 0.065 81.305 0.000 5.273 6.847
## .ls_p1 5.163 0.076 67.748 0.000 5.163 5.705
## .ls_p2 5.709 0.061 93.294 0.000 5.709 7.857
## .ls_p3 4.973 0.072 69.489 0.000 4.973 5.852
## SUP_Parents 0.000 0.000 0.000
## SUP_Friends 0.000 0.000 0.000
## SE_Academic 0.000 0.000 0.000
## SE_Social 0.000 0.000 0.000
## LS 0.000 0.000 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.269 0.065 4.121 0.000 0.269 0.215
## .sup_parents_p2 0.249 0.090 2.779 0.005 0.249 0.178
## .sup_parents_p3 0.615 0.130 4.744 0.000 0.615 0.405
## .sup_friends_p1 0.271 0.128 2.115 0.034 0.271 0.165
## .sup_friends_p2 0.347 0.102 3.401 0.001 0.347 0.287
## .sup_friends_p3 0.497 0.187 2.661 0.008 0.497 0.304
## .se_acad_p1 0.115 0.034 3.433 0.001 0.115 0.210
## .se_acad_p2 0.163 0.027 6.033 0.000 0.163 0.380
## .se_acad_p3 0.155 0.035 4.389 0.000 0.155 0.277
## .se_social_p1 0.152 0.026 5.911 0.000 0.152 0.287
## .se_social_p2 0.148 0.031 4.785 0.000 0.148 0.271
## .se_social_p3 0.297 0.040 7.467 0.000 0.297 0.501
## .ls_p1 0.412 0.066 6.241 0.000 0.412 0.503
## .ls_p2 0.283 0.100 2.837 0.005 0.283 0.535
## .ls_p3 0.330 0.049 6.683 0.000 0.330 0.458
## SUP_Parents 0.982 0.202 4.855 0.000 1.000 1.000
## SUP_Friends 1.367 0.253 5.402 0.000 1.000 1.000
## SE_Academic 0.434 0.069 6.264 0.000 1.000 1.000
## SE_Social 0.378 0.077 4.920 0.000 1.000 1.000
## LS 0.407 0.112 3.626 0.000 1.000 1.000
##
##
## Group 2 [east]:
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sup_parents_p1 1.000 0.894 0.875
## sup_parents_p2 0.943 0.078 12.081 0.000 0.843 0.863
## sup_parents_p3 0.984 0.076 12.951 0.000 0.880 0.857
## SUP_Friends =~
## sup_friends_p1 1.000 0.840 0.896
## sup_friends_p2 0.773 0.074 10.415 0.000 0.649 0.873
## sup_friends_p3 0.825 0.066 12.548 0.000 0.693 0.811
## SE_Academic =~
## se_acad_p1 1.000 0.700 0.873
## se_acad_p2 0.772 0.069 11.230 0.000 0.541 0.812
## se_acad_p3 0.807 0.082 9.812 0.000 0.565 0.777
## SE_Social =~
## se_social_p1 1.000 0.666 0.856
## se_social_p2 0.851 0.074 11.521 0.000 0.567 0.917
## se_social_p3 0.889 0.069 12.839 0.000 0.591 0.746
## LS =~
## ls_p1 1.000 0.726 0.764
## ls_p2 0.727 0.100 7.280 0.000 0.528 0.729
## ls_p3 0.843 0.109 7.708 0.000 0.611 0.725
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents ~~
## SUP_Friends 0.025 0.070 0.358 0.720 0.033 0.033
## SE_Academic 0.250 0.063 3.978 0.000 0.399 0.399
## SE_Social 0.349 0.122 2.873 0.004 0.587 0.587
## LS 0.486 0.123 3.964 0.000 0.749 0.749
## SUP_Friends ~~
## SE_Academic 0.075 0.054 1.379 0.168 0.127 0.127
## SE_Social 0.179 0.048 3.726 0.000 0.321 0.321
## LS 0.142 0.057 2.490 0.013 0.233 0.233
## SE_Academic ~~
## SE_Social 0.268 0.054 4.981 0.000 0.576 0.576
## LS 0.228 0.059 3.870 0.000 0.449 0.449
## SE_Social ~~
## LS 0.361 0.086 4.186 0.000 0.747 0.747
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 6.004 0.086 70.016 0.000 6.004 5.876
## .sup_parents_p2 6.056 0.082 73.867 0.000 6.056 6.199
## .sup_parents_p3 5.863 0.086 68.070 0.000 5.863 5.712
## .sup_friends_p1 5.901 0.079 75.067 0.000 5.901 6.299
## .sup_friends_p2 6.120 0.062 98.103 0.000 6.120 8.233
## .sup_friends_p3 6.123 0.072 85.429 0.000 6.123 7.169
## .se_acad_p1 5.327 0.067 79.100 0.000 5.327 6.638
## .se_acad_p2 5.527 0.056 98.863 0.000 5.527 8.296
## .se_acad_p3 5.521 0.061 90.458 0.000 5.521 7.591
## .se_social_p1 5.364 0.065 82.218 0.000 5.364 6.900
## .se_social_p2 5.626 0.052 108.519 0.000 5.626 9.107
## .se_social_p3 5.608 0.066 84.339 0.000 5.608 7.078
## .ls_p1 5.221 0.080 65.475 0.000 5.221 5.495
## .ls_p2 5.846 0.061 96.252 0.000 5.846 8.077
## .ls_p3 5.470 0.071 77.293 0.000 5.470 6.486
## SUP_Parents 0.000 0.000 0.000
## SUP_Friends 0.000 0.000 0.000
## SE_Academic 0.000 0.000 0.000
## SE_Social 0.000 0.000 0.000
## LS 0.000 0.000 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.244 0.057 4.315 0.000 0.244 0.234
## .sup_parents_p2 0.244 0.054 4.486 0.000 0.244 0.255
## .sup_parents_p3 0.279 0.052 5.359 0.000 0.279 0.265
## .sup_friends_p1 0.173 0.058 2.972 0.003 0.173 0.197
## .sup_friends_p2 0.131 0.028 4.710 0.000 0.131 0.238
## .sup_friends_p3 0.249 0.058 4.310 0.000 0.249 0.342
## .se_acad_p1 0.154 0.040 3.841 0.000 0.154 0.238
## .se_acad_p2 0.151 0.030 4.979 0.000 0.151 0.341
## .se_acad_p3 0.210 0.039 5.342 0.000 0.210 0.397
## .se_social_p1 0.161 0.036 4.439 0.000 0.161 0.267
## .se_social_p2 0.061 0.016 3.828 0.000 0.061 0.159
## .se_social_p3 0.278 0.037 7.549 0.000 0.278 0.443
## .ls_p1 0.376 0.062 6.104 0.000 0.376 0.417
## .ls_p2 0.245 0.059 4.167 0.000 0.245 0.468
## .ls_p3 0.337 0.069 4.902 0.000 0.337 0.474
## SUP_Parents 0.800 0.211 3.784 0.000 1.000 1.000
## SUP_Friends 0.705 0.135 5.211 0.000 1.000 1.000
## SE_Academic 0.490 0.066 7.400 0.000 1.000 1.000
## SE_Social 0.443 0.102 4.354 0.000 1.000 1.000
## LS 0.526 0.106 4.962 0.000 1.000 1.000
Metric (weak) measurement invariance
In the second step, the loading parameters of the measurement model are restricted to equality between the groups. The model fit and a model comparison with the previous model allow conclusions regarding the hypothesis of a “weak” (metric) measurement invariance across groups.
<- sem(model_measurement,
fit_metric data = data_sem,
estimator = "MLM",
group = "region",
group.equal = "loadings")
summary(fit_metric, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 59 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 110
## Number of equality constraints 10
##
## Number of observations per group:
## west 141
## east 142
##
## Model Test User Model:
## Standard Robust
## Test Statistic 338.264 286.015
## Degrees of freedom 170 170
## P-value (Chi-square) 0.000 0.000
## Scaling correction factor 1.183
## Satorra-Bentler correction
## Test statistic for each group:
## west 175.893 148.725
## east 162.370 137.290
##
## Model Test Baseline Model:
##
## Test statistic 2786.197 1986.569
## Degrees of freedom 210 210
## P-value 0.000 0.000
## Scaling correction factor 1.403
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.935 0.935
## Tucker-Lewis Index (TLI) 0.919 0.919
##
## Robust Comparative Fit Index (CFI) 0.945
## Robust Tucker-Lewis Index (TLI) 0.932
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4183.249 -4183.249
## Loglikelihood unrestricted model (H1) -4014.118 -4014.118
##
## Akaike (AIC) 8566.499 8566.499
## Bayesian (BIC) 8931.043 8931.043
## Sample-size adjusted Bayesian (BIC) 8613.942 8613.942
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.084 0.069
## 90 Percent confidence interval - lower 0.071 0.056
## 90 Percent confidence interval - upper 0.097 0.082
## P-value RMSEA <= 0.05 0.000 0.009
##
## Robust RMSEA 0.076
## 90 Percent confidence interval - lower 0.060
## 90 Percent confidence interval - upper 0.091
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.064 0.064
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Structured
##
##
## Group 1 [west]:
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sp_pr_1 1.000 1.014 0.896
## sp_pr_2 (.p2.) 1.011 0.059 17.203 0.000 1.025 0.888
## sp_pr_3 (.p3.) 0.979 0.061 15.945 0.000 0.993 0.787
## SUP_Friends =~
## sp_fr_1 1.000 1.186 0.920
## sp_fr_2 (.p5.) 0.785 0.056 14.065 0.000 0.931 0.844
## sp_fr_3 (.p6.) 0.869 0.064 13.494 0.000 1.031 0.821
## SE_Academic =~
## s_cd_p1 1.000 0.675 0.900
## s_cd_p2 (.p8.) 0.781 0.047 16.619 0.000 0.527 0.794
## s_cd_p3 (.p9.) 0.891 0.058 15.320 0.000 0.601 0.827
## SE_Social =~
## s_scl_1 1.000 0.639 0.861
## s_scl_2 (.11.) 0.914 0.063 14.426 0.000 0.585 0.820
## s_scl_3 (.12.) 0.888 0.065 13.742 0.000 0.568 0.722
## LS =~
## ls_p1 1.000 0.666 0.725
## ls_p2 (.14.) 0.752 0.077 9.816 0.000 0.501 0.691
## ls_p3 (.15.) 0.897 0.082 10.921 0.000 0.597 0.712
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents ~~
## SUP_Friends 0.226 0.113 1.999 0.046 0.188 0.188
## SE_Academic 0.174 0.065 2.672 0.008 0.254 0.254
## SE_Social 0.227 0.063 3.602 0.000 0.350 0.350
## LS 0.357 0.062 5.762 0.000 0.528 0.528
## SUP_Friends ~~
## SE_Academic 0.014 0.073 0.193 0.847 0.018 0.018
## SE_Social 0.194 0.061 3.179 0.001 0.255 0.255
## LS 0.189 0.085 2.234 0.026 0.240 0.240
## SE_Academic ~~
## SE_Social 0.263 0.043 6.165 0.000 0.611 0.611
## LS 0.234 0.060 3.886 0.000 0.521 0.521
## SE_Social ~~
## LS 0.312 0.066 4.729 0.000 0.732 0.732
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 5.947 0.094 63.141 0.000 5.947 5.254
## .sup_parents_p2 5.798 0.100 58.172 0.000 5.798 5.022
## .sup_parents_p3 5.574 0.104 53.734 0.000 5.574 4.419
## .sup_friends_p1 5.670 0.108 52.613 0.000 5.670 4.398
## .sup_friends_p2 5.901 0.093 63.697 0.000 5.901 5.350
## .sup_friends_p3 5.858 0.108 54.386 0.000 5.858 4.665
## .se_acad_p1 4.982 0.062 79.820 0.000 4.982 6.647
## .se_acad_p2 5.165 0.055 93.644 0.000 5.165 7.785
## .se_acad_p3 4.899 0.063 77.797 0.000 4.899 6.742
## .se_social_p1 5.216 0.061 85.032 0.000 5.216 7.023
## .se_social_p2 5.328 0.062 85.534 0.000 5.328 7.474
## .se_social_p3 5.273 0.065 81.305 0.000 5.273 6.704
## .ls_p1 5.163 0.076 67.748 0.000 5.163 5.617
## .ls_p2 5.709 0.061 93.294 0.000 5.709 7.877
## .ls_p3 4.973 0.072 69.489 0.000 4.973 5.931
## SUP_Parents 0.000 0.000 0.000
## SUP_Friends 0.000 0.000 0.000
## SE_Academic 0.000 0.000 0.000
## SE_Social 0.000 0.000 0.000
## LS 0.000 0.000 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.252 0.065 3.892 0.000 0.252 0.197
## .sup_parents_p2 0.281 0.085 3.321 0.001 0.281 0.211
## .sup_parents_p3 0.605 0.130 4.664 0.000 0.605 0.380
## .sup_friends_p1 0.256 0.121 2.109 0.035 0.256 0.154
## .sup_friends_p2 0.350 0.094 3.727 0.000 0.350 0.287
## .sup_friends_p3 0.514 0.173 2.969 0.003 0.514 0.326
## .se_acad_p1 0.107 0.033 3.278 0.001 0.107 0.190
## .se_acad_p2 0.163 0.027 6.024 0.000 0.163 0.370
## .se_acad_p3 0.167 0.032 5.207 0.000 0.167 0.315
## .se_social_p1 0.143 0.025 5.664 0.000 0.143 0.259
## .se_social_p2 0.166 0.029 5.789 0.000 0.166 0.327
## .se_social_p3 0.296 0.040 7.336 0.000 0.296 0.479
## .ls_p1 0.401 0.066 6.113 0.000 0.401 0.475
## .ls_p2 0.275 0.096 2.847 0.004 0.275 0.523
## .ls_p3 0.347 0.047 7.323 0.000 0.347 0.493
## SUP_Parents 1.029 0.189 5.436 0.000 1.000 1.000
## SUP_Friends 1.407 0.239 5.879 0.000 1.000 1.000
## SE_Academic 0.455 0.066 6.872 0.000 1.000 1.000
## SE_Social 0.409 0.074 5.491 0.000 1.000 1.000
## LS 0.444 0.101 4.405 0.000 1.000 1.000
##
##
## Group 2 [east]:
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sp_pr_1 1.000 0.873 0.867
## sp_pr_2 (.p2.) 1.011 0.059 17.203 0.000 0.883 0.878
## sp_pr_3 (.p3.) 0.979 0.061 15.945 0.000 0.855 0.847
## SUP_Friends =~
## sp_fr_1 1.000 0.825 0.889
## sp_fr_2 (.p5.) 0.785 0.056 14.065 0.000 0.647 0.873
## sp_fr_3 (.p6.) 0.869 0.064 13.494 0.000 0.717 0.824
## SE_Academic =~
## s_cd_p1 1.000 0.679 0.859
## s_cd_p2 (.p8.) 0.781 0.047 16.619 0.000 0.530 0.805
## s_cd_p3 (.p9.) 0.891 0.058 15.320 0.000 0.605 0.804
## SE_Social =~
## s_scl_1 1.000 0.639 0.839
## s_scl_2 (.11.) 0.914 0.063 14.426 0.000 0.584 0.930
## s_scl_3 (.12.) 0.888 0.065 13.742 0.000 0.567 0.730
## LS =~
## ls_p1 1.000 0.702 0.750
## ls_p2 (.14.) 0.752 0.077 9.816 0.000 0.528 0.728
## ls_p3 (.15.) 0.897 0.082 10.921 0.000 0.630 0.737
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents ~~
## SUP_Friends 0.029 0.067 0.432 0.666 0.040 0.040
## SE_Academic 0.234 0.060 3.936 0.000 0.395 0.395
## SE_Social 0.326 0.107 3.029 0.002 0.584 0.584
## LS 0.462 0.116 3.983 0.000 0.754 0.754
## SUP_Friends ~~
## SE_Academic 0.071 0.052 1.364 0.173 0.127 0.127
## SE_Social 0.174 0.046 3.798 0.000 0.331 0.331
## LS 0.136 0.054 2.508 0.012 0.235 0.235
## SE_Academic ~~
## SE_Social 0.245 0.051 4.830 0.000 0.565 0.565
## LS 0.215 0.056 3.801 0.000 0.450 0.450
## SE_Social ~~
## LS 0.333 0.079 4.221 0.000 0.743 0.743
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 6.004 0.086 70.016 0.000 6.004 5.962
## .sup_parents_p2 6.056 0.082 73.867 0.000 6.056 6.026
## .sup_parents_p3 5.863 0.086 68.070 0.000 5.863 5.809
## .sup_friends_p1 5.901 0.079 75.067 0.000 5.901 6.363
## .sup_friends_p2 6.120 0.062 98.103 0.000 6.120 8.251
## .sup_friends_p3 6.123 0.072 85.429 0.000 6.123 7.036
## .se_acad_p1 5.327 0.067 79.100 0.000 5.327 6.739
## .se_acad_p2 5.527 0.056 98.863 0.000 5.527 8.396
## .se_acad_p3 5.521 0.061 90.458 0.000 5.521 7.338
## .se_social_p1 5.364 0.065 82.218 0.000 5.364 7.048
## .se_social_p2 5.626 0.052 108.519 0.000 5.626 8.963
## .se_social_p3 5.608 0.066 84.339 0.000 5.608 7.218
## .ls_p1 5.221 0.080 65.475 0.000 5.221 5.572
## .ls_p2 5.846 0.061 96.252 0.000 5.846 8.058
## .ls_p3 5.470 0.071 77.293 0.000 5.470 6.405
## SUP_Parents 0.000 0.000 0.000
## SUP_Friends 0.000 0.000 0.000
## SE_Academic 0.000 0.000 0.000
## SE_Social 0.000 0.000 0.000
## LS 0.000 0.000 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.252 0.052 4.853 0.000 0.252 0.248
## .sup_parents_p2 0.231 0.055 4.238 0.000 0.231 0.229
## .sup_parents_p3 0.288 0.052 5.570 0.000 0.288 0.282
## .sup_friends_p1 0.180 0.056 3.203 0.001 0.180 0.209
## .sup_friends_p2 0.131 0.025 5.206 0.000 0.131 0.238
## .sup_friends_p3 0.244 0.058 4.192 0.000 0.244 0.322
## .se_acad_p1 0.164 0.041 4.052 0.000 0.164 0.263
## .se_acad_p2 0.153 0.028 5.403 0.000 0.153 0.352
## .se_acad_p3 0.200 0.039 5.138 0.000 0.200 0.354
## .se_social_p1 0.171 0.035 4.909 0.000 0.171 0.296
## .se_social_p2 0.053 0.016 3.281 0.001 0.053 0.134
## .se_social_p3 0.282 0.037 7.666 0.000 0.282 0.468
## .ls_p1 0.385 0.063 6.078 0.000 0.385 0.438
## .ls_p2 0.247 0.058 4.250 0.000 0.247 0.470
## .ls_p3 0.333 0.069 4.807 0.000 0.333 0.456
## SUP_Parents 0.762 0.189 4.038 0.000 1.000 1.000
## SUP_Friends 0.680 0.123 5.542 0.000 1.000 1.000
## SE_Academic 0.461 0.064 7.240 0.000 1.000 1.000
## SE_Social 0.408 0.087 4.693 0.000 1.000 1.000
## LS 0.493 0.102 4.843 0.000 1.000 1.000
anova(fit_configural, fit_metric)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_configural 160 8577.0 8978 328.78
## fit_metric 170 8566.5 8931 338.26 7.368 10 0.6903
The comparison is not significant, thus metric measurement invariance can be assumed.
Scalar (strong) measurement invariance
In the next step, the intercepts of the manifest variables are additionally restricted to equality. Model fit and a model comparison with the previous model allow conclusions regarding the hypothesis of scalar (strong) measurement invariance. Scalar measurement invariance means that there is no differential item-functioning across groups.
However, this does not mean that a complete measurement invariance is guaranteed, because the procedure is not able to detect group-specific uniform response styles (all items of a construct affected by the same kind of bias).
<- sem(model_measurement,
fit_scalar data = data_sem,
estimator = "MLM",
group = "region",
group.equal = c("loadings", "intercepts"))
summary(fit_scalar, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 137 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 115
## Number of equality constraints 25
##
## Number of observations per group:
## west 141
## east 142
##
## Model Test User Model:
## Standard Robust
## Test Statistic 397.337 347.114
## Degrees of freedom 180 180
## P-value (Chi-square) 0.000 0.000
## Scaling correction factor 1.145
## Satorra-Bentler correction
## Test statistic for each group:
## west 200.588 175.234
## east 196.749 171.880
##
## Model Test Baseline Model:
##
## Test statistic 2786.197 1986.569
## Degrees of freedom 210 210
## P-value 0.000 0.000
## Scaling correction factor 1.403
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.916 0.906
## Tucker-Lewis Index (TLI) 0.902 0.890
##
## Robust Comparative Fit Index (CFI) 0.923
## Robust Tucker-Lewis Index (TLI) 0.910
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4212.786 -4212.786
## Loglikelihood unrestricted model (H1) -4014.118 -4014.118
##
## Akaike (AIC) 8605.572 8605.572
## Bayesian (BIC) 8933.662 8933.662
## Sample-size adjusted Bayesian (BIC) 8648.271 8648.271
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.092 0.081
## 90 Percent confidence interval - lower 0.080 0.069
## 90 Percent confidence interval - upper 0.105 0.093
## P-value RMSEA <= 0.05 0.000 0.000
##
## Robust RMSEA 0.087
## 90 Percent confidence interval - lower 0.073
## 90 Percent confidence interval - upper 0.100
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.070 0.070
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Structured
##
##
## Group 1 [west]:
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sp_pr_1 1.000 1.003 0.888
## sp_pr_2 (.p2.) 1.030 0.059 17.363 0.000 1.033 0.891
## sp_pr_3 (.p3.) 0.999 0.064 15.712 0.000 1.002 0.790
## SUP_Friends =~
## sp_fr_1 1.000 1.183 0.919
## sp_fr_2 (.p5.) 0.789 0.055 14.253 0.000 0.933 0.845
## sp_fr_3 (.p6.) 0.875 0.065 13.511 0.000 1.035 0.822
## SE_Academic =~
## s_cd_p1 1.000 0.643 0.876
## s_cd_p2 (.p8.) 0.823 0.045 18.446 0.000 0.529 0.799
## s_cd_p3 (.p9.) 0.995 0.059 16.934 0.000 0.640 0.847
## SE_Social =~
## s_scl_1 1.000 0.622 0.845
## s_scl_2 (.11.) 0.958 0.065 14.624 0.000 0.596 0.828
## s_scl_3 (.12.) 0.936 0.068 13.818 0.000 0.583 0.733
## LS =~
## ls_p1 1.000 0.634 0.695
## ls_p2 (.14.) 0.773 0.073 10.533 0.000 0.490 0.678
## ls_p3 (.15.) 0.985 0.085 11.648 0.000 0.624 0.723
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents ~~
## SUP_Friends 0.221 0.112 1.975 0.048 0.187 0.187
## SE_Academic 0.166 0.062 2.671 0.008 0.258 0.258
## SE_Social 0.218 0.061 3.574 0.000 0.349 0.349
## LS 0.345 0.060 5.785 0.000 0.543 0.543
## SUP_Friends ~~
## SE_Academic 0.011 0.070 0.154 0.878 0.014 0.014
## SE_Social 0.193 0.059 3.281 0.001 0.262 0.262
## LS 0.184 0.081 2.274 0.023 0.246 0.246
## SE_Academic ~~
## SE_Social 0.243 0.041 5.988 0.000 0.607 0.607
## LS 0.216 0.055 3.912 0.000 0.531 0.531
## SE_Social ~~
## LS 0.291 0.063 4.651 0.000 0.737 0.737
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sp_pr_1 (.46.) 5.881 0.092 63.988 0.000 5.881 5.209
## .sp_pr_2 (.47.) 5.834 0.096 61.080 0.000 5.834 5.035
## .sp_pr_3 (.48.) 5.643 0.095 59.667 0.000 5.643 4.449
## .sp_fr_1 (.49.) 5.653 0.106 53.463 0.000 5.653 4.390
## .sp_fr_2 (.50.) 5.911 0.087 67.816 0.000 5.911 5.353
## .sp_fr_3 (.51.) 5.884 0.098 59.785 0.000 5.884 4.676
## .s_cd_p1 (.52.) 4.934 0.061 80.488 0.000 4.934 6.720
## .s_cd_p2 (.53.) 5.155 0.053 97.691 0.000 5.155 7.782
## .s_cd_p3 (.54.) 4.969 0.061 81.104 0.000 4.969 6.581
## .s_scl_1 (.55.) 5.162 0.059 86.932 0.000 5.162 7.006
## .s_scl_2 (.56.) 5.362 0.059 91.279 0.000 5.362 7.453
## .s_scl_3 (.57.) 5.317 0.060 89.151 0.000 5.317 6.687
## .ls_p1 (.58.) 5.059 0.070 72.023 0.000 5.059 5.550
## .ls_p2 (.59.) 5.675 0.056 101.151 0.000 5.675 7.854
## .ls_p3 (.60.) 5.095 0.067 76.322 0.000 5.095 5.902
## SUP_Prn 0.000 0.000 0.000
## SUP_Frn 0.000 0.000 0.000
## SE_Acdm 0.000 0.000 0.000
## SE_Socl 0.000 0.000 0.000
## LS 0.000 0.000 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.269 0.064 4.178 0.000 0.269 0.211
## .sup_parents_p2 0.276 0.084 3.288 0.001 0.276 0.206
## .sup_parents_p3 0.605 0.129 4.681 0.000 0.605 0.376
## .sup_friends_p1 0.259 0.119 2.179 0.029 0.259 0.156
## .sup_friends_p2 0.349 0.094 3.702 0.000 0.349 0.286
## .sup_friends_p3 0.512 0.172 2.972 0.003 0.512 0.324
## .se_acad_p1 0.126 0.030 4.136 0.000 0.126 0.233
## .se_acad_p2 0.159 0.027 5.954 0.000 0.159 0.362
## .se_acad_p3 0.161 0.033 4.850 0.000 0.161 0.282
## .se_social_p1 0.156 0.025 6.315 0.000 0.156 0.287
## .se_social_p2 0.162 0.029 5.660 0.000 0.162 0.314
## .se_social_p3 0.293 0.040 7.236 0.000 0.293 0.463
## .ls_p1 0.429 0.064 6.703 0.000 0.429 0.517
## .ls_p2 0.282 0.096 2.935 0.003 0.282 0.540
## .ls_p3 0.356 0.047 7.555 0.000 0.356 0.477
## SUP_Parents 1.006 0.187 5.384 0.000 1.000 1.000
## SUP_Friends 1.399 0.237 5.900 0.000 1.000 1.000
## SE_Academic 0.414 0.061 6.730 0.000 1.000 1.000
## SE_Social 0.387 0.071 5.419 0.000 1.000 1.000
## LS 0.402 0.094 4.280 0.000 1.000 1.000
##
##
## Group 2 [east]:
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sp_pr_1 1.000 0.861 0.859
## sp_pr_2 (.p2.) 1.030 0.059 17.363 0.000 0.886 0.879
## sp_pr_3 (.p3.) 0.999 0.064 15.712 0.000 0.860 0.849
## SUP_Friends =~
## sp_fr_1 1.000 0.822 0.888
## sp_fr_2 (.p5.) 0.789 0.055 14.253 0.000 0.648 0.873
## sp_fr_3 (.p6.) 0.875 0.065 13.511 0.000 0.719 0.825
## SE_Academic =~
## s_cd_p1 1.000 0.640 0.826
## s_cd_p2 (.p8.) 0.823 0.045 18.446 0.000 0.527 0.805
## s_cd_p3 (.p9.) 0.995 0.059 16.934 0.000 0.637 0.814
## SE_Social =~
## s_scl_1 1.000 0.615 0.820
## s_scl_2 (.11.) 0.958 0.065 14.624 0.000 0.589 0.936
## s_scl_3 (.12.) 0.936 0.068 13.818 0.000 0.576 0.734
## LS =~
## ls_p1 1.000 0.667 0.719
## ls_p2 (.14.) 0.773 0.073 10.533 0.000 0.516 0.716
## ls_p3 (.15.) 0.985 0.085 11.648 0.000 0.657 0.745
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents ~~
## SUP_Friends 0.028 0.066 0.424 0.672 0.039 0.039
## SE_Academic 0.218 0.057 3.853 0.000 0.396 0.396
## SE_Social 0.307 0.102 3.021 0.003 0.579 0.579
## LS 0.439 0.112 3.923 0.000 0.765 0.765
## SUP_Friends ~~
## SE_Academic 0.068 0.049 1.373 0.170 0.129 0.129
## SE_Social 0.171 0.044 3.878 0.000 0.338 0.338
## LS 0.129 0.052 2.506 0.012 0.236 0.236
## SE_Academic ~~
## SE_Social 0.221 0.048 4.637 0.000 0.560 0.560
## LS 0.195 0.052 3.739 0.000 0.457 0.457
## SE_Social ~~
## LS 0.306 0.074 4.147 0.000 0.746 0.746
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sp_pr_1 (.46.) 5.881 0.092 63.988 0.000 5.881 5.866
## .sp_pr_2 (.47.) 5.834 0.096 61.080 0.000 5.834 5.787
## .sp_pr_3 (.48.) 5.643 0.095 59.667 0.000 5.643 5.572
## .sp_fr_1 (.49.) 5.653 0.106 53.463 0.000 5.653 6.105
## .sp_fr_2 (.50.) 5.911 0.087 67.816 0.000 5.911 7.964
## .sp_fr_3 (.51.) 5.884 0.098 59.785 0.000 5.884 6.748
## .s_cd_p1 (.52.) 4.934 0.061 80.488 0.000 4.934 6.366
## .s_cd_p2 (.53.) 5.155 0.053 97.691 0.000 5.155 7.885
## .s_cd_p3 (.54.) 4.969 0.061 81.104 0.000 4.969 6.351
## .s_scl_1 (.55.) 5.162 0.059 86.932 0.000 5.162 6.877
## .s_scl_2 (.56.) 5.362 0.059 91.279 0.000 5.362 8.520
## .s_scl_3 (.57.) 5.317 0.060 89.151 0.000 5.317 6.780
## .ls_p1 (.58.) 5.059 0.070 72.023 0.000 5.059 5.457
## .ls_p2 (.59.) 5.675 0.056 101.151 0.000 5.675 7.879
## .ls_p3 (.60.) 5.095 0.067 76.322 0.000 5.095 5.777
## SUP_Prn 0.188 0.117 1.605 0.108 0.218 0.218
## SUP_Frn 0.260 0.127 2.048 0.041 0.317 0.317
## SE_Acdm 0.465 0.084 5.521 0.000 0.726 0.726
## SE_Socl 0.265 0.079 3.342 0.001 0.430 0.430
## LS 0.261 0.090 2.886 0.004 0.392 0.392
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.264 0.051 5.174 0.000 0.264 0.263
## .sup_parents_p2 0.231 0.055 4.207 0.000 0.231 0.227
## .sup_parents_p3 0.286 0.052 5.485 0.000 0.286 0.279
## .sup_friends_p1 0.182 0.056 3.221 0.001 0.182 0.212
## .sup_friends_p2 0.131 0.025 5.184 0.000 0.131 0.237
## .sup_friends_p3 0.243 0.058 4.164 0.000 0.243 0.320
## .se_acad_p1 0.191 0.042 4.535 0.000 0.191 0.318
## .se_acad_p2 0.150 0.028 5.287 0.000 0.150 0.351
## .se_acad_p3 0.207 0.041 5.068 0.000 0.207 0.338
## .se_social_p1 0.185 0.035 5.284 0.000 0.185 0.328
## .se_social_p2 0.049 0.016 2.997 0.003 0.049 0.124
## .se_social_p3 0.283 0.037 7.721 0.000 0.283 0.461
## .ls_p1 0.415 0.064 6.478 0.000 0.415 0.483
## .ls_p2 0.253 0.058 4.349 0.000 0.253 0.487
## .ls_p3 0.347 0.071 4.876 0.000 0.347 0.446
## SUP_Parents 0.741 0.185 4.010 0.000 1.000 1.000
## SUP_Friends 0.676 0.122 5.555 0.000 1.000 1.000
## SE_Academic 0.410 0.060 6.886 0.000 1.000 1.000
## SE_Social 0.378 0.081 4.662 0.000 1.000 1.000
## LS 0.445 0.096 4.615 0.000 1.000 1.000
anova(fit_metric, fit_scalar)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_metric 170 8566.5 8931.0 338.26
## fit_scalar 180 8605.6 8933.7 397.34 118.43 10 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
This time the comparison is highly significant. The assumption of identical intercepts and thus “strong” (scalar) measurement invariance must therefore be rejected. Another criterion frequently cited in the literature is that the more restrictive model (despite the significant chi-square value) should only have a CFI/TLI that is less 0.01 lower than the CFI/TLI of the less restrictive model.
<- fitMeasures(fit_metric)[names = c("cfi.robust", "tli.robust")]
m <- fitMeasures(fit_scalar)[names = c("cfi.robust", "tli.robust")]
s round(m - s, 3)
## cfi.robust tli.robust
## 0.022 0.022
Here we are above this cut-off value. Thus, strong measurement invariance is not supported.
13.3.2 Multi-group analyses for the structural model (moderation analyses)
In addition to measurement invariance, multi-group analysis can be used to check the invariance of structural paths. This allows to check moderation hypotheses (group variables as moderators) for single or multiple structural paths.
First, however, a procedure is presented that checks the entire structural model (i.e. all structural path coefficients) for equivalence (in addition to the weak measurement invariance).
Overall moderation test / equivalence of the structural model across groups
<- sem(model,
fit_allequal data = data_sem,
estimator = "MLM",
group = "region",
group.equal = c("loadings", "regressions"))
This model is often compared to the weak (and not the strong) measurement invariance model because for CFAs/SEMs where the mean structure is not of interest the metric measurement invariance (equivalence of factor loadings) is sufficient.
We first have to estimate the full model with metric equivalence restrictions (which we have done so far only for the measurement model):
<- sem(model,
fit_structure_metric data = data_sem,
estimator = "MLM",
group = "region",
group.equal = c("loadings"))
summary(fit_structure_metric, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-9 ended normally after 50 iterations
##
## Estimator ML
## Optimization method NLMINB
## Number of model parameters 110
## Number of equality constraints 10
##
## Number of observations per group:
## west 141
## east 142
##
## Model Test User Model:
## Standard Robust
## Test Statistic 338.264 286.015
## Degrees of freedom 170 170
## P-value (Chi-square) 0.000 0.000
## Scaling correction factor 1.183
## Satorra-Bentler correction
## Test statistic for each group:
## west 175.893 148.724
## east 162.370 137.290
##
## Model Test Baseline Model:
##
## Test statistic 2786.197 1986.569
## Degrees of freedom 210 210
## P-value 0.000 0.000
## Scaling correction factor 1.403
##
## User Model versus Baseline Model:
##
## Comparative Fit Index (CFI) 0.935 0.935
## Tucker-Lewis Index (TLI) 0.919 0.919
##
## Robust Comparative Fit Index (CFI) 0.945
## Robust Tucker-Lewis Index (TLI) 0.932
##
## Loglikelihood and Information Criteria:
##
## Loglikelihood user model (H0) -4183.249 -4183.249
## Loglikelihood unrestricted model (H1) -4014.118 -4014.118
##
## Akaike (AIC) 8566.499 8566.499
## Bayesian (BIC) 8931.043 8931.043
## Sample-size adjusted Bayesian (BIC) 8613.942 8613.942
##
## Root Mean Square Error of Approximation:
##
## RMSEA 0.084 0.069
## 90 Percent confidence interval - lower 0.071 0.056
## 90 Percent confidence interval - upper 0.097 0.082
## P-value RMSEA <= 0.05 0.000 0.009
##
## Robust RMSEA 0.076
## 90 Percent confidence interval - lower 0.060
## 90 Percent confidence interval - upper 0.091
##
## Standardized Root Mean Square Residual:
##
## SRMR 0.064 0.064
##
## Parameter Estimates:
##
## Standard errors Robust.sem
## Information Expected
## Information saturated (h1) model Structured
##
##
## Group 1 [west]:
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sp_pr_1 1.000 1.014 0.896
## sp_pr_2 (.p2.) 1.011 0.059 17.203 0.000 1.025 0.888
## sp_pr_3 (.p3.) 0.979 0.061 15.945 0.000 0.993 0.787
## SUP_Friends =~
## sp_fr_1 1.000 1.186 0.920
## sp_fr_2 (.p5.) 0.785 0.056 14.065 0.000 0.931 0.844
## sp_fr_3 (.p6.) 0.869 0.064 13.494 0.000 1.031 0.821
## SE_Academic =~
## s_cd_p1 1.000 0.675 0.900
## s_cd_p2 (.p8.) 0.781 0.047 16.619 0.000 0.527 0.794
## s_cd_p3 (.p9.) 0.891 0.058 15.320 0.000 0.601 0.827
## SE_Social =~
## s_scl_1 1.000 0.639 0.861
## s_scl_2 (.11.) 0.914 0.063 14.426 0.000 0.585 0.820
## s_scl_3 (.12.) 0.888 0.065 13.742 0.000 0.568 0.722
## LS =~
## ls_p1 1.000 0.666 0.725
## ls_p2 (.14.) 0.752 0.077 9.816 0.000 0.501 0.691
## ls_p3 (.15.) 0.897 0.082 10.921 0.000 0.597 0.712
##
## Regressions:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SE_Academic ~
## SUP_Parents 0.173 0.074 2.347 0.019 0.260 0.260
## SUP_Friends -0.018 0.054 -0.328 0.743 -0.031 -0.031
## SE_Social ~
## SUP_Parents 0.197 0.071 2.772 0.006 0.313 0.313
## SUP_Friends 0.106 0.045 2.331 0.020 0.197 0.197
## LS ~
## SE_Academic 0.107 0.111 0.963 0.336 0.108 0.108
## SE_Social 0.574 0.125 4.596 0.000 0.551 0.551
## SUP_Parents 0.197 0.052 3.804 0.000 0.300 0.300
## SUP_Friends 0.023 0.049 0.470 0.639 0.041 0.041
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .SE_Academic ~~
## .SE_Social 0.228 0.038 5.952 0.000 0.596 0.596
## SUP_Parents ~~
## SUP_Friends 0.226 0.113 1.999 0.046 0.188 0.188
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 5.947 0.094 63.141 0.000 5.947 5.254
## .sup_parents_p2 5.798 0.100 58.172 0.000 5.798 5.022
## .sup_parents_p3 5.574 0.104 53.734 0.000 5.574 4.419
## .sup_friends_p1 5.670 0.108 52.613 0.000 5.670 4.398
## .sup_friends_p2 5.901 0.093 63.697 0.000 5.901 5.350
## .sup_friends_p3 5.858 0.108 54.386 0.000 5.858 4.665
## .se_acad_p1 4.982 0.062 79.820 0.000 4.982 6.647
## .se_acad_p2 5.165 0.055 93.644 0.000 5.165 7.785
## .se_acad_p3 4.899 0.063 77.797 0.000 4.899 6.742
## .se_social_p1 5.216 0.061 85.032 0.000 5.216 7.023
## .se_social_p2 5.328 0.062 85.534 0.000 5.328 7.474
## .se_social_p3 5.273 0.065 81.305 0.000 5.273 6.704
## .ls_p1 5.163 0.076 67.748 0.000 5.163 5.617
## .ls_p2 5.709 0.061 93.294 0.000 5.709 7.877
## .ls_p3 4.973 0.072 69.489 0.000 4.973 5.931
## SUP_Parents 0.000 0.000 0.000
## SUP_Friends 0.000 0.000 0.000
## .SE_Academic 0.000 0.000 0.000
## .SE_Social 0.000 0.000 0.000
## .LS 0.000 0.000 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.252 0.065 3.892 0.000 0.252 0.197
## .sup_parents_p2 0.281 0.085 3.321 0.001 0.281 0.211
## .sup_parents_p3 0.605 0.130 4.664 0.000 0.605 0.380
## .sup_friends_p1 0.256 0.121 2.109 0.035 0.256 0.154
## .sup_friends_p2 0.350 0.094 3.727 0.000 0.350 0.287
## .sup_friends_p3 0.514 0.173 2.969 0.003 0.514 0.326
## .se_acad_p1 0.107 0.033 3.278 0.001 0.107 0.190
## .se_acad_p2 0.163 0.027 6.024 0.000 0.163 0.370
## .se_acad_p3 0.167 0.032 5.207 0.000 0.167 0.315
## .se_social_p1 0.143 0.025 5.664 0.000 0.143 0.259
## .se_social_p2 0.166 0.029 5.789 0.000 0.166 0.327
## .se_social_p3 0.296 0.040 7.336 0.000 0.296 0.479
## .ls_p1 0.401 0.066 6.113 0.000 0.401 0.475
## .ls_p2 0.275 0.096 2.847 0.004 0.275 0.523
## .ls_p3 0.347 0.047 7.323 0.000 0.347 0.493
## SUP_Parents 1.029 0.189 5.436 0.000 1.000 1.000
## SUP_Friends 1.407 0.239 5.879 0.000 1.000 1.000
## .SE_Academic 0.425 0.060 7.124 0.000 0.935 0.935
## .SE_Social 0.344 0.060 5.729 0.000 0.840 0.840
## .LS 0.165 0.047 3.523 0.000 0.372 0.372
##
##
## Group 2 [east]:
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SUP_Parents =~
## sp_pr_1 1.000 0.873 0.867
## sp_pr_2 (.p2.) 1.011 0.059 17.203 0.000 0.883 0.878
## sp_pr_3 (.p3.) 0.979 0.061 15.945 0.000 0.855 0.847
## SUP_Friends =~
## sp_fr_1 1.000 0.825 0.889
## sp_fr_2 (.p5.) 0.785 0.056 14.065 0.000 0.647 0.873
## sp_fr_3 (.p6.) 0.869 0.064 13.494 0.000 0.717 0.824
## SE_Academic =~
## s_cd_p1 1.000 0.679 0.859
## s_cd_p2 (.p8.) 0.781 0.047 16.619 0.000 0.530 0.805
## s_cd_p3 (.p9.) 0.891 0.058 15.320 0.000 0.605 0.804
## SE_Social =~
## s_scl_1 1.000 0.639 0.839
## s_scl_2 (.11.) 0.914 0.063 14.426 0.000 0.584 0.930
## s_scl_3 (.12.) 0.888 0.065 13.742 0.000 0.567 0.730
## LS =~
## ls_p1 1.000 0.702 0.750
## ls_p2 (.14.) 0.752 0.077 9.816 0.000 0.528 0.728
## ls_p3 (.15.) 0.897 0.082 10.921 0.000 0.630 0.737
##
## Regressions:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## SE_Academic ~
## SUP_Parents 0.304 0.068 4.468 0.000 0.391 0.391
## SUP_Friends 0.091 0.071 1.279 0.201 0.111 0.111
## SE_Social ~
## SUP_Parents 0.418 0.081 5.166 0.000 0.572 0.572
## SUP_Friends 0.238 0.052 4.621 0.000 0.308 0.308
## LS ~
## SE_Academic 0.003 0.112 0.025 0.980 0.003 0.003
## SE_Social 0.466 0.116 4.006 0.000 0.424 0.424
## SUP_Parents 0.404 0.083 4.847 0.000 0.502 0.502
## SUP_Friends 0.063 0.052 1.226 0.220 0.074 0.074
##
## Covariances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .SE_Academic ~~
## .SE_Social 0.130 0.031 4.240 0.000 0.438 0.438
## SUP_Parents ~~
## SUP_Friends 0.029 0.067 0.432 0.666 0.040 0.040
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 6.004 0.086 70.016 0.000 6.004 5.962
## .sup_parents_p2 6.056 0.082 73.867 0.000 6.056 6.026
## .sup_parents_p3 5.863 0.086 68.070 0.000 5.863 5.809
## .sup_friends_p1 5.901 0.079 75.067 0.000 5.901 6.363
## .sup_friends_p2 6.120 0.062 98.103 0.000 6.120 8.251
## .sup_friends_p3 6.123 0.072 85.429 0.000 6.123 7.036
## .se_acad_p1 5.327 0.067 79.100 0.000 5.327 6.739
## .se_acad_p2 5.527 0.056 98.863 0.000 5.527 8.396
## .se_acad_p3 5.521 0.061 90.458 0.000 5.521 7.338
## .se_social_p1 5.364 0.065 82.218 0.000 5.364 7.048
## .se_social_p2 5.626 0.052 108.519 0.000 5.626 8.963
## .se_social_p3 5.608 0.066 84.339 0.000 5.608 7.218
## .ls_p1 5.221 0.080 65.475 0.000 5.221 5.572
## .ls_p2 5.846 0.061 96.252 0.000 5.846 8.058
## .ls_p3 5.470 0.071 77.293 0.000 5.470 6.405
## SUP_Parents 0.000 0.000 0.000
## SUP_Friends 0.000 0.000 0.000
## .SE_Academic 0.000 0.000 0.000
## .SE_Social 0.000 0.000 0.000
## .LS 0.000 0.000 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|) Std.lv Std.all
## .sup_parents_p1 0.252 0.052 4.853 0.000 0.252 0.248
## .sup_parents_p2 0.231 0.055 4.238 0.000 0.231 0.229
## .sup_parents_p3 0.288 0.052 5.570 0.000 0.288 0.282
## .sup_friends_p1 0.180 0.056 3.203 0.001 0.180 0.209
## .sup_friends_p2 0.131 0.025 5.206 0.000 0.131 0.238
## .sup_friends_p3 0.244 0.058 4.192 0.000 0.244 0.322
## .se_acad_p1 0.164 0.041 4.052 0.000 0.164 0.263
## .se_acad_p2 0.153 0.028 5.403 0.000 0.153 0.352
## .se_acad_p3 0.200 0.039 5.138 0.000 0.200 0.354
## .se_social_p1 0.171 0.035 4.909 0.000 0.171 0.296
## .se_social_p2 0.053 0.016 3.281 0.001 0.053 0.134
## .se_social_p3 0.282 0.037 7.666 0.000 0.282 0.468
## .ls_p1 0.385 0.063 6.078 0.000 0.385 0.438
## .ls_p2 0.247 0.058 4.250 0.000 0.247 0.470
## .ls_p3 0.333 0.069 4.807 0.000 0.333 0.456
## SUP_Parents 0.762 0.189 4.038 0.000 1.000 1.000
## SUP_Friends 0.680 0.123 5.542 0.000 1.000 1.000
## .SE_Academic 0.383 0.060 6.361 0.000 0.831 0.831
## .SE_Social 0.230 0.043 5.340 0.000 0.565 0.565
## .LS 0.142 0.043 3.326 0.001 0.288 0.288
Now we can compare with the equal structural paths model:
anova(fit_structure_metric, fit_allequal)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_structure_metric 170 8566.5 8931.0 338.26
## fit_allequal 178 8568.0 8903.4 355.74 15.768 8 0.04582 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
The \(H_0\) that all parameters related to the structural model are equal across East and West German adolescents has to be rejected. In the following, we try to pinpoint the moderation effect with regard to the structural path coefficients.
Moderated mediation analysis
We can conduct a moderated mediation analysis by using a group variable (factor) as a moderator variable for the paths in the structural model.
In order to test the differences of individual paths between the groups (moderation), we need an alternative method for equality constraints based on explicit naming of the individual parameters.
We will show this first for all 8 regression paths individually, and then for the 4 combined paths representing the specific indirect effects in the model.
Moderation tests for the 8 individual paths
1) Support from Parents \(\rightarrow\) Academic Self-Efficacy
<- '
model_b1 # 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 ~ c(b1, b1)*SUP_Parents + SUP_Friends
SE_Social ~ SUP_Parents + SUP_Friends
LS ~ SUP_Parents + SUP_Friends + SE_Academic + SE_Social
# Residual covariances
SE_Academic ~~ SE_Social
'
<- sem(model_b1,
fit_b1 data = data_sem,
estimator = "MLM",
group = "region",
group.equal = "loadings")
anova(fit_b1, fit_structure_metric)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_structure_metric 170 8566.5 8931.0 338.26
## fit_b1 171 8566.5 8927.4 340.23 2.0146 1 0.1558
2) Support from Parents \(\rightarrow\) Social Self-Efficacy
<- '
model_b2 # 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 ~ SUP_Parents + SUP_Friends
SE_Social ~ c(b2, b2)*SUP_Parents + SUP_Friends
LS ~ SUP_Parents + SUP_Friends + SE_Academic + SE_Social
# Residual covariances
SE_Academic ~~ SE_Social
'
<- sem(model_b2,
fit_b2 data = data_sem,
estimator = "MLM",
group = "region",
group.equal = "loadings")
anova(fit_b2, fit_structure_metric)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_structure_metric 170 8566.5 8931.0 338.26
## fit_b2 171 8571.9 8932.8 345.69 3.26 1 0.07099 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
3) Support from Friends \(\rightarrow\) Academic Self-Efficacy
<- '
model_b3 # 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 ~ SUP_Parents + c(b3, b3)*SUP_Friends
SE_Social ~ SUP_Parents + SUP_Friends
LS ~ SUP_Parents + SUP_Friends + SE_Academic + SE_Social
# Residual covariances
SE_Academic ~~ SE_Social
'
<- sem(model_b3,
fit_b3 data = data_sem,
estimator = "MLM",
group = "region",
group.equal = "loadings")
anova(fit_b3, fit_structure_metric)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_structure_metric 170 8566.5 8931.0 338.26
## fit_b3 171 8565.9 8926.8 339.71 1.4056 1 0.2358
4) Support from Friends \(\rightarrow\) Social Self-Efficacy
<- '
model_b4 # 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 ~ SUP_Parents + SUP_Friends
SE_Social ~ SUP_Parents + c(b4, b4)*SUP_Friends
LS ~ SUP_Parents + SUP_Friends + SE_Academic + SE_Social
# Residual covariances
SE_Academic ~~ SE_Social
'
<- sem(model_b4,
fit_b4 data = data_sem,
estimator = "MLM",
group = "region",
group.equal = "loadings")
anova(fit_b4, fit_structure_metric)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_structure_metric 170 8566.5 8931.0 338.26
## fit_b4 171 8567.4 8928.3 341.20 3.1669 1 0.07515 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
5) Support from Parents \(\rightarrow\) Life Satisfaction
<- '
model_b5 # 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 ~ SUP_Parents + SUP_Friends
SE_Social ~ SUP_Parents + SUP_Friends
LS ~ c(b5, b5)*SUP_Parents + SUP_Friends + SE_Academic + SE_Social
# Residual covariances
SE_Academic ~~ SE_Social
'
<- sem(model_b5,
fit_b5 data = data_sem,
estimator = "MLM",
group = "region",
group.equal = "loadings")
anova(fit_b5, fit_structure_metric)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_structure_metric 170 8566.5 8931 338.26
## fit_b5 171 8569.1 8930 342.86 7.6089 1 0.005808 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
6) Support from Friends \(\rightarrow\) Life Satisfaction
<- '
model_b6 # 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 ~ SUP_Parents + SUP_Friends
SE_Social ~ SUP_Parents + SUP_Friends
LS ~ SUP_Parents + c(b6, b6)*SUP_Friends + SE_Academic + SE_Social
# Residual covariances
SE_Academic ~~ SE_Social
'
<- sem(model_b6,
fit_b6 data = data_sem,
estimator = "MLM",
group = "region",
group.equal = "loadings")
anova(fit_b6, fit_structure_metric)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_structure_metric 170 8566.5 8931.0 338.26
## fit_b6 171 8564.7 8925.6 338.51 0.32262 1 0.57
7) Academic Self-Efficacy \(\rightarrow\) Life Satisfaction
<- '
model_b7 # 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 ~ SUP_Parents + SUP_Friends
SE_Social ~ SUP_Parents + SUP_Friends
LS ~ SUP_Parents + SUP_Friends + c(b7, b7)*SE_Academic + SE_Social
# Residual covariances
SE_Academic ~~ SE_Social
'
<- sem(model_b7,
fit_b7 data = data_sem,
estimator = "MLM",
group = "region",
group.equal = "loadings")
anova(fit_b7, fit_structure_metric)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_structure_metric 170 8566.5 8931.0 338.26
## fit_b7 171 8565.0 8925.9 338.74 0.39601 1 0.5292
8) Social Self-Efficacy \(\rightarrow\) Life Satisfaction
<- '
model_b8 # 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 ~ SUP_Parents + SUP_Friends
SE_Social ~ SUP_Parents + SUP_Friends
LS ~ SUP_Parents + SUP_Friends + SE_Academic + c(b8, b8)*SE_Social
# Residual covariances
SE_Academic ~~ SE_Social
'
<- sem(model_b8,
fit_b8 data = data_sem,
estimator = "MLM",
group = "region",
group.equal = "loadings")
anova(fit_b8, fit_structure_metric)
## Scaled Chi-Squared Difference Test (method = "satorra.bentler.2001")
##
## lavaan NOTE:
## The "Chisq" column contains standard test statistics, not the
## robust test that should be reported per model. A robust difference
## test is a function of two standard (not robust) statistics.
##
## Df AIC BIC Chisq Chisq diff Df diff Pr(>Chisq)
## fit_structure_metric 170 8566.5 8931.0 338.26
## fit_b8 171 8564.8 8925.7 338.61 0.39308 1 0.5307
The results show that only the path b5, the direct effect of SUP_Parents on LS was significantly different across groups.
According to the structural metric invariance model (fit_structure_metric
) the effect was b5 = 0.300 for west German adolescents, and b7 = 0.502 for east German adolescents.
13.4 References
Rosseel, Y. (2012). lavaan: An R Package for Structural Equation Modeling. Journal of Statistical Software, 48(2), 1-36. URL http://www.jstatsoft.org/v48/i02/.
Little, T. D., Cunningham, W. A., Shahar, G., & Widaman, K. F. (2002). To parcel or not to parcel: Exploring the question, weighing the merits. Structural Equation Modelling, 9(2), 151–173.