Department of Industrial Psychology

Stellenbosch University

South Africa

Read the data, choose an estimator, specify the grouping variable

The data should be stored in a .csv file. Each column in the .csv file should have a heading.

library(lavaan)
library(psych)
library(semTools)
mydata <- read.csv(file.choose())

#describe(mydata)

### Choose an estimator from "ML", "MLM", "MLR"
estimator <- "MLM"

### Type the name of the grouping variable
group <- "Country_habitat"

Specify the measurement model

mymodel <- '
Stress =~ GWS1 + GWS2 + GWS3 + GWS4 + GWS5 + GWS6 + GWS7 + GWS8 + GWS9
'

Fit the baseline model to the observed data

# Estimate and inspect the item parameters
fit.mymodel <- cfa(model = mymodel, 
                   data = mydata,
                   estimator = estimator)

Inspect the model fit and the factor loadings of the baseline model

summary(fit.mymodel, standardized = TRUE, fit.measures = TRUE)
## lavaan 0.6.15 ended normally after 22 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        18
## 
##   Number of observations                          1377
## 
## Model Test User Model:
##                                               Standard      Scaled
##   Test Statistic                               808.572     576.336
##   Degrees of freedom                                27          27
##   P-value (Chi-square)                           0.000       0.000
##   Scaling correction factor                                  1.403
##     Satorra-Bentler correction                                    
## 
## Model Test Baseline Model:
## 
##   Test statistic                              6506.495    4273.114
##   Degrees of freedom                                36          36
##   P-value                                        0.000       0.000
##   Scaling correction factor                                  1.523
## 
## User Model versus Baseline Model:
## 
##   Comparative Fit Index (CFI)                    0.879       0.870
##   Tucker-Lewis Index (TLI)                       0.839       0.827
##                                                                   
##   Robust Comparative Fit Index (CFI)                         0.881
##   Robust Tucker-Lewis Index (TLI)                            0.841
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)             -14826.170  -14826.170
##   Loglikelihood unrestricted model (H1)     -14421.884  -14421.884
##                                                                   
##   Akaike (AIC)                               29688.341   29688.341
##   Bayesian (BIC)                             29782.439   29782.439
##   Sample-size adjusted Bayesian (SABIC)      29725.260   29725.260
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.145       0.122
##   90 Percent confidence interval - lower         0.136       0.114
##   90 Percent confidence interval - upper         0.154       0.129
##   P-value H_0: RMSEA <= 0.050                    0.000       0.000
##   P-value H_0: RMSEA >= 0.080                    1.000       1.000
##                                                                   
##   Robust RMSEA                                               0.144
##   90 Percent confidence interval - lower                     0.134
##   90 Percent confidence interval - upper                     0.154
##   P-value H_0: Robust RMSEA <= 0.050                         0.000
##   P-value H_0: Robust RMSEA >= 0.080                         1.000
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.057       0.057
## 
## 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
##   Stress =~                                                             
##     GWS1              1.000                               0.810    0.762
##     GWS2              1.114    0.025   44.563    0.000    0.902    0.814
##     GWS3              0.963    0.033   29.149    0.000    0.780    0.737
##     GWS4              0.895    0.039   23.233    0.000    0.725    0.668
##     GWS5              0.763    0.031   24.228    0.000    0.618    0.665
##     GWS6              0.831    0.029   28.291    0.000    0.673    0.748
##     GWS7              0.813    0.034   24.209    0.000    0.659    0.627
##     GWS8              0.837    0.033   25.583    0.000    0.678    0.723
##     GWS9              0.771    0.034   22.972    0.000    0.624    0.651
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .GWS1              0.474    0.021   22.512    0.000    0.474    0.419
##    .GWS2              0.414    0.023   18.140    0.000    0.414    0.337
##    .GWS3              0.511    0.030   16.999    0.000    0.511    0.457
##    .GWS4              0.651    0.030   22.004    0.000    0.651    0.553
##    .GWS5              0.481    0.022   22.205    0.000    0.481    0.557
##    .GWS6              0.356    0.018   19.805    0.000    0.356    0.440
##    .GWS7              0.671    0.029   23.433    0.000    0.671    0.607
##    .GWS8              0.420    0.023   18.098    0.000    0.420    0.478
##    .GWS9              0.530    0.026   20.110    0.000    0.530    0.576
##     Stress            0.656    0.039   16.682    0.000    1.000    1.000

Activate the measurement invariance function

measurement.invariance <- function(fit.config, fit.weak, fit.strong, fit.strict, fit.means) {
config.fit <- fitmeasures(fit.config, c("cfi.robust", "tli.robust", "rmsea.robust", "srmr", "BIC", "chisq.scaled", "df.scaled", "pvalue.scaled"))
weak.fit <- fitmeasures(fit.weak, c("cfi.robust", "tli.robust", "rmsea.robust", "srmr", "BIC", "chisq.scaled", "df.scaled", "pvalue.scaled"))
strong.fit <- fitmeasures(fit.strong, c("cfi.robust", "tli.robust", "rmsea.robust", "srmr", "BIC", "chisq.scaled", "df.scaled", "pvalue.scaled"))
strict.fit <- fitmeasures(fit.strict, c("cfi.robust", "tli.robust", "rmsea.robust", "srmr", "BIC", "chisq.scaled", "df.scaled", "pvalue.scaled"))
means.fit <- fitmeasures(fit.means, c("cfi.robust", "tli.robust", "rmsea.robust", "srmr", "BIC", "chisq.scaled", "df.scaled", "pvalue.scaled"))
fit.models <- rbind(config.fit, weak.fit, strong.fit, strict.fit, means.fit)
delta.weak <- config.fit - weak.fit
delta.strong <- weak.fit - strong.fit
delta.strict <- strong.fit - strict.fit
delta.means <- strict.fit - means.fit
delta.models <- rbind(delta.weak, delta.strong, delta.strict, delta.means)
fit.models
delta.models
anova.models <- anova(fit.config, fit.weak, fit.strong, fit.strict, fit.means)
compare.models <- list(anova = anova.models, model.fit = fit.models, model.delta = delta.models[ , c(1, 3, 5)])
compare.models
}

Fit the measurement invariance models to the observed data

##### Configural invariance
fit.config <- cfa(mymodel, data = mydata, group = group, estimator = estimator)
#summary(fit.config)

####### Weak invariance
fit.weak <- cfa(mymodel, data = mydata, group = group, estimator = estimator, group.equal ="loadings")
#summary(fit.weak)

####### Strong invariance
fit.strong <- cfa(mymodel, data = mydata, group = group, estimator = estimator,
                  group.equal = c("loadings", "intercepts"))
#summary(fit.strong)

####### Strict invariance
fit.strict <- cfa(mymodel, data = mydata, group = group, estimator = estimator,
                  group.equal = c("loadings", "intercepts",
                                                     "residuals"))
#summary(fit.strict)

####### Equal factor means
fit.means <- cfa(mymodel, data = mydata, group = group, estimator = estimator,
                 group.equal = c("loadings", "intercepts",
                                                    "residuals", "means"))
#summary(fit.means)

###################################################################
# Run the measurement invariance function in the MeasInvar.R file #
###################################################################
measurement.invariance(fit.config, fit.weak, fit.strong, fit.strict, fit.means)
## $anova
## 
## 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.config 54 29471 29754  842.56                                  
## fit.weak   62 29464 29704  850.86      8.292       8     0.4055    
## fit.strong 70 29618 29817 1021.49    260.932       8  < 2.2e-16 ***
## fit.strict 79 29664 29816 1085.56     58.199       9  2.976e-09 ***
## fit.means  80 29687 29833 1109.87     25.893       1  3.608e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## $model.fit
##            cfi.robust tli.robust rmsea.robust       srmr      bic chisq.scaled
## config.fit  0.8807417  0.8409889    0.1435070 0.05366521 29753.55     591.7743
## weak.fit    0.8806962  0.8614536    0.1339543 0.05570739 29704.03     621.4061
## strong.fit  0.8549340  0.8507893    0.1390142 0.06820978 29816.84     793.3926
## strict.fit  0.8464985  0.8600999    0.1346072 0.07333484 29815.86     857.3154
## means.fit   0.8428583  0.8585725    0.1353400 0.08323715 29832.94     879.3561
##            df.scaled pvalue.scaled
## config.fit        54             0
## weak.fit          62             0
## strong.fit        70             0
## strict.fit        79             0
## means.fit         80             0
## 
## $model.delta
##                cfi.robust  rmsea.robust          bic
## delta.weak   4.546861e-05  0.0095526256   49.5202773
## delta.strong 2.576218e-02 -0.0050598926 -112.8109903
## delta.strict 8.435499e-03  0.0044070506    0.9834126
## delta.means  3.640199e-03 -0.0007328253  -17.0823393

Inspect the factor loadings, intercepts and error variances of a fitted model

Type here the name of the fitted model that you want to inspect. This will typically be the best fitting model that was identified in the previous step.

summary(fit.strong, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6.15 ended normally after 38 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        55
##   Number of equality constraints                    17
## 
##   Number of observations per group:                   
##     2                                              793
##     1                                              584
## 
## Model Test User Model:
##                                               Standard      Scaled
##   Test Statistic                              1021.491     793.393
##   Degrees of freedom                                70          70
##   P-value (Chi-square)                           0.000       0.000
##   Scaling correction factor                                  1.287
##     Satorra-Bentler correction                                    
##   Test statistic for each group:
##     2                                          494.400     384.001
##     1                                          527.091     409.392
## 
## Model Test Baseline Model:
## 
##   Test statistic                              6523.400    4555.388
##   Degrees of freedom                                72          72
##   P-value                                        0.000       0.000
##   Scaling correction factor                                  1.432
## 
## User Model versus Baseline Model:
## 
##   Comparative Fit Index (CFI)                    0.853       0.839
##   Tucker-Lewis Index (TLI)                       0.848       0.834
##                                                                   
##   Robust Comparative Fit Index (CFI)                         0.855
##   Robust Tucker-Lewis Index (TLI)                            0.851
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)             -14771.097  -14771.097
##   Loglikelihood unrestricted model (H1)     -14260.351  -14260.351
##                                                                   
##   Akaike (AIC)                               29618.193   29618.193
##   Bayesian (BIC)                             29816.844   29816.844
##   Sample-size adjusted Bayesian (SABIC)      29696.133   29696.133
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.141       0.123
##   90 Percent confidence interval - lower         0.133       0.116
##   90 Percent confidence interval - upper         0.148       0.129
##   P-value H_0: RMSEA <= 0.050                    0.000       0.000
##   P-value H_0: RMSEA >= 0.080                    1.000       1.000
##                                                                   
##   Robust RMSEA                                               0.139
##   90 Percent confidence interval - lower                     0.130
##   90 Percent confidence interval - upper                     0.148
##   P-value H_0: Robust RMSEA <= 0.050                         0.000
##   P-value H_0: Robust RMSEA >= 0.080                         1.000
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.068       0.068
## 
## Parameter Estimates:
## 
##   Standard errors                           Robust.sem
##   Information                                 Expected
##   Information saturated (h1) model          Structured
## 
## 
## Group 1 [2]:
## 
## Latent Variables:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   Stress =~                                                             
##     GWS1              1.000                               0.865    0.791
##     GWS2    (.p2.)    1.115    0.025   44.382    0.000    0.965    0.834
##     GWS3    (.p3.)    0.969    0.033   29.531    0.000    0.838    0.750
##     GWS4    (.p4.)    0.899    0.039   23.294    0.000    0.778    0.686
##     GWS5    (.p5.)    0.765    0.031   24.549    0.000    0.662    0.667
##     GWS6    (.p6.)    0.833    0.030   28.159    0.000    0.721    0.767
##     GWS7    (.p7.)    0.822    0.033   25.075    0.000    0.711    0.688
##     GWS8    (.p8.)    0.836    0.033   25.409    0.000    0.723    0.740
##     GWS9    (.p9.)    0.770    0.033   23.073    0.000    0.666    0.648
## 
## Intercepts:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .GWS1    (.20.)    2.699    0.036   75.742    0.000    2.699    2.467
##    .GWS2    (.21.)    2.252    0.039   57.787    0.000    2.252    1.945
##    .GWS3    (.22.)    2.313    0.036   65.071    0.000    2.313    2.069
##    .GWS4    (.23.)    2.329    0.036   64.392    0.000    2.329    2.055
##    .GWS5    (.24.)    2.099    0.031   68.180    0.000    2.099    2.115
##    .GWS6    (.25.)    2.158    0.031   69.325    0.000    2.158    2.298
##    .GWS7    (.26.)    2.707    0.034   80.274    0.000    2.707    2.620
##    .GWS8    (.27.)    2.052    0.032   63.127    0.000    2.052    2.098
##    .GWS9    (.28.)    2.060    0.032   64.571    0.000    2.060    2.005
##     Stress            0.000                               0.000    0.000
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .GWS1              0.448    0.026   17.091    0.000    0.448    0.374
##    .GWS2              0.408    0.029   14.291    0.000    0.408    0.305
##    .GWS3              0.547    0.045   12.226    0.000    0.547    0.438
##    .GWS4              0.679    0.040   16.852    0.000    0.679    0.529
##    .GWS5              0.547    0.031   17.617    0.000    0.547    0.555
##    .GWS6              0.363    0.024   15.178    0.000    0.363    0.411
##    .GWS7              0.562    0.032   17.390    0.000    0.562    0.526
##    .GWS8              0.433    0.030   14.509    0.000    0.433    0.453
##    .GWS9              0.612    0.038   16.026    0.000    0.612    0.580
##     Stress            0.749    0.050   14.892    0.000    1.000    1.000
## 
## 
## Group 2 [1]:
## 
## Latent Variables:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   Stress =~                                                             
##     GWS1              1.000                               0.704    0.702
##     GWS2    (.p2.)    1.115    0.025   44.382    0.000    0.785    0.769
##     GWS3    (.p3.)    0.969    0.033   29.531    0.000    0.682    0.708
##     GWS4    (.p4.)    0.899    0.039   23.294    0.000    0.632    0.630
##     GWS5    (.p5.)    0.765    0.031   24.549    0.000    0.538    0.654
##     GWS6    (.p6.)    0.833    0.030   28.159    0.000    0.586    0.706
##     GWS7    (.p7.)    0.822    0.033   25.075    0.000    0.578    0.537
##     GWS8    (.p8.)    0.836    0.033   25.409    0.000    0.588    0.677
##     GWS9    (.p9.)    0.770    0.033   23.073    0.000    0.542    0.641
## 
## Intercepts:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .GWS1    (.20.)    2.699    0.036   75.742    0.000    2.699    2.691
##    .GWS2    (.21.)    2.252    0.039   57.787    0.000    2.252    2.208
##    .GWS3    (.22.)    2.313    0.036   65.071    0.000    2.313    2.403
##    .GWS4    (.23.)    2.329    0.036   64.392    0.000    2.329    2.321
##    .GWS5    (.24.)    2.099    0.031   68.180    0.000    2.099    2.551
##    .GWS6    (.25.)    2.158    0.031   69.325    0.000    2.158    2.599
##    .GWS7    (.26.)    2.707    0.034   80.274    0.000    2.707    2.516
##    .GWS8    (.27.)    2.052    0.032   63.127    0.000    2.052    2.364
##    .GWS9    (.28.)    2.060    0.032   64.571    0.000    2.060    2.439
##     Stress           -0.223    0.044   -5.049    0.000   -0.317   -0.317
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .GWS1              0.511    0.033   15.287    0.000    0.511    0.508
##    .GWS2              0.424    0.036   11.903    0.000    0.424    0.408
##    .GWS3              0.462    0.034   13.759    0.000    0.462    0.499
##    .GWS4              0.607    0.040   15.349    0.000    0.607    0.603
##    .GWS5              0.388    0.026   15.011    0.000    0.388    0.572
##    .GWS6              0.346    0.026   13.571    0.000    0.346    0.502
##    .GWS7              0.824    0.044   18.583    0.000    0.824    0.711
##    .GWS8              0.408    0.033   12.455    0.000    0.408    0.541
##    .GWS9              0.420    0.033   12.795    0.000    0.420    0.589
##     Stress            0.495    0.042   11.743    0.000    1.000    1.000

Perform Lagrange multiplier tests to identify parameters that should be freely estimated

lavTestScore(fit.strong)
## Warning in lavTestScore(fit.strong): lavaan WARNING: se is not `standard'; not
## implemented yet; falling back to ordinary score test
## $test
## 
## total score test:
## 
##    test      X2 df p.value
## 1 score 173.413 17       0
## 
## $uni
## 
## univariate score tests:
## 
##      lhs op   rhs     X2 df p.value
## 1   .p2. == .p31.  0.417  1   0.519
## 2   .p3. == .p32.  7.943  1   0.005
## 3   .p4. == .p33.  0.537  1   0.464
## 4   .p5. == .p34.  0.030  1   0.863
## 5   .p6. == .p35.  0.379  1   0.538
## 6   .p7. == .p36.  7.786  1   0.005
## 7   .p8. == .p37.  4.583  1   0.032
## 8   .p9. == .p38.  0.058  1   0.809
## 9  .p20. == .p49.  6.564  1   0.010
## 10 .p21. == .p50. 13.114  1   0.000
## 11 .p22. == .p51.  7.656  1   0.006
## 12 .p23. == .p52.  0.727  1   0.394
## 13 .p24. == .p53. 22.339  1   0.000
## 14 .p25. == .p54.  3.098  1   0.078
## 15 .p26. == .p55. 88.060  1   0.000
## 16 .p27. == .p56. 37.233  1   0.000
## 17 .p28. == .p57.  2.999  1   0.083

References

de Bruin, G. P. & Taylor, N. (2005). Development of the Sources of Work Stress Inventory. South African Journal of Psychology, 35, 748-765.

de Bruin, G. P. (2006). Dimensionality of the General Work Stress Scale. SA Journal of Industrial Psychology, 32(4), 68-75.