# principles and practice of sem, 5th ed.
# rex b. kline, guilford press, 2023

# chapter 14, table 14.1, analysis 1
# single-factor cfa model for the kabc-1 analyzed
# in the 10-year-old normative sample for the test

# to avoid the problem that some R packages share the same name 
# for different functions, all functions are specified next as 

# package::function

# which prevents masking, or the default hiding of 
# a function with a redundant name from a package used next
date()
## [1] "Mon Sep 29 17:30:27 2025"
v <- R.Version()
print(paste0(v$language, " version ", v$major, ".",
 v$minor, " (", v$year, "-", v$month, "-", v$day, ")"))
## [1] "R version 4.5.1 (2025-06-13)"
library(lavaan)
## This is lavaan 0.6-20
## lavaan is FREE software! Please report any bugs.
# get citation information
citation("lavaan", auto = TRUE)
## To cite package 'lavaan' in publications use:
## 
##   Rosseel Y, Jorgensen TD, De Wilde L (2025). _lavaan: Latent Variable
##   Analysis_. doi:10.32614/CRAN.package.lavaan
##   <https://doi.org/10.32614/CRAN.package.lavaan>, R package version
##   0.6-20, <https://CRAN.R-project.org/package=lavaan>.
## 
## A BibTeX entry for LaTeX users is
## 
##   @Manual{,
##     title = {lavaan: Latent Variable Analysis},
##     author = {Yves Rosseel and Terrence D. Jorgensen and Luc {De Wilde}},
##     year = {2025},
##     note = {R package version 0.6-20},
##     url = {https://CRAN.R-project.org/package=lavaan},
##     doi = {10.32614/CRAN.package.lavaan},
##   }
# input the correlations in lower diagnonal form
kabcLower.cor <- '
 1.00
 .39 1.00
 .35  .67 1.00
 .21  .11  .16 1.00
 .32  .27  .29  .38 1.00
 .40  .29  .28  .30  .47 1.00
 .39  .32  .30  .31  .42  .41 1.00
 .39  .29  .37  .42  .58  .51  .42 1.00 '
# name the variables and convert to full correlation matrix
# hm, hand movements; nr, number recall; wo, word order; gc, gestalt closure; 
# tr, triangles; sm, spatial memory; ma, matrix analogies; ps, photo series
kabc.cor <- lavaan::getCov(kabcLower.cor, names = c("hm", "nr", "wo",
 "gc", "tr", "sm", "ma", "ps"))
# display correlations
kabc.cor
##      hm   nr   wo   gc   tr   sm   ma   ps
## hm 1.00 0.39 0.35 0.21 0.32 0.40 0.39 0.39
## nr 0.39 1.00 0.67 0.11 0.27 0.29 0.32 0.29
## wo 0.35 0.67 1.00 0.16 0.29 0.28 0.30 0.37
## gc 0.21 0.11 0.16 1.00 0.38 0.30 0.31 0.42
## tr 0.32 0.27 0.29 0.38 1.00 0.47 0.42 0.58
## sm 0.40 0.29 0.28 0.30 0.47 1.00 0.41 0.51
## ma 0.39 0.32 0.30 0.31 0.42 0.41 1.00 0.42
## ps 0.39 0.29 0.37 0.42 0.58 0.51 0.42 1.00
# add the standard deviations and convert to covariances
# This gives the covariance matrix. 
kabc.cov <- lavaan::cor2cov(kabc.cor, sds = c(3.40,2.40,2.90,2.70,2.70,4.20,2.80,3.00))

# display covariances
kabc.cov
##         hm     nr     wo     gc     tr      sm     ma    ps
## hm 11.5600 3.1824 3.4510 1.9278 2.9376  5.7120 3.7128 3.978
## nr  3.1824 5.7600 4.6632 0.7128 1.7496  2.9232 2.1504 2.088
## wo  3.4510 4.6632 8.4100 1.2528 2.2707  3.4104 2.4360 3.219
## gc  1.9278 0.7128 1.2528 7.2900 2.7702  3.4020 2.3436 3.402
## tr  2.9376 1.7496 2.2707 2.7702 7.2900  5.3298 3.1752 4.698
## sm  5.7120 2.9232 3.4104 3.4020 5.3298 17.6400 4.8216 6.426
## ma  3.7128 2.1504 2.4360 2.3436 3.1752  4.8216 7.8400 3.528
## ps  3.9780 2.0880 3.2190 3.4020 4.6980  6.4260 3.5280 9.000
# specify 1-factor cfa model
# single factor (general ability)
# indicator hm automatically
# specified as reference variable

kabc1.model <- '
General =~ hm + nr + wo + gc + tr + sm + ma + ps '
# fit model to data
# variances calculated with N in the denominator, not N - 1
#This uses the covariance matrix. Lavaan default is the covariance matrix. 
kabc1 <- lavaan::sem(kabc1.model, sample.cov = kabc.cov, sample.nobs = 200)
lavaan::summary(kabc1, fit.measures = TRUE, standardized = TRUE, rsquare = TRUE)
## lavaan 0.6-20 ended normally after 36 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        16
## 
##   Number of observations                           200
## 
## Model Test User Model:
##                                                       
##   Test statistic                               105.427
##   Degrees of freedom                                20
##   P-value (Chi-square)                           0.000
## 
## Model Test Baseline Model:
## 
##   Test statistic                               498.336
##   Degrees of freedom                                28
##   P-value                                        0.000
## 
## User Model versus Baseline Model:
## 
##   Comparative Fit Index (CFI)                    0.818
##   Tucker-Lewis Index (TLI)                       0.746
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)              -3812.592
##   Loglikelihood unrestricted model (H1)      -3759.878
##                                                       
##   Akaike (AIC)                                7657.183
##   Bayesian (BIC)                              7709.956
##   Sample-size adjusted Bayesian (SABIC)       7659.267
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.146
##   90 Percent confidence interval - lower         0.119
##   90 Percent confidence interval - upper         0.174
##   P-value H_0: RMSEA <= 0.050                    0.000
##   P-value H_0: RMSEA >= 0.080                    1.000
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.084
## 
## Parameter Estimates:
## 
##   Standard errors                             Standard
##   Information                                 Expected
##   Information saturated (h1) model          Structured
## 
## Latent Variables:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   General =~                                                            
##     hm                1.000                               1.921    0.566
##     nr                0.636    0.111    5.708    0.000    1.221    0.510
##     wo                0.805    0.136    5.910    0.000    1.547    0.535
##     gc                0.659    0.123    5.361    0.000    1.265    0.470
##     tr                0.963    0.138    6.984    0.000    1.850    0.687
##     sm                1.433    0.211    6.796    0.000    2.752    0.657
##     ma                0.883    0.137    6.459    0.000    1.696    0.607
##     ps                1.166    0.159    7.324    0.000    2.240    0.749
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .hm                7.812    0.863    9.049    0.000    7.812    0.679
##    .nr                4.240    0.456    9.294    0.000    4.240    0.740
##    .wo                5.975    0.650    9.195    0.000    5.975    0.714
##    .gc                5.652    0.599    9.432    0.000    5.652    0.779
##    .tr                3.831    0.468    8.186    0.000    3.831    0.528
##    .sm                9.979    1.179    8.463    0.000    9.979    0.569
##    .ma                4.925    0.558    8.822    0.000    4.925    0.631
##    .ps                3.936    0.531    7.410    0.000    3.936    0.440
##     General           3.690    0.921    4.008    0.000    1.000    1.000
## 
## R-Square:
##                    Estimate
##     hm                0.321
##     nr                0.260
##     wo                0.286
##     gc                0.221
##     tr                0.472
##     sm                0.431
##     ma                0.369
##     ps                0.560
# residuals
lavaan::residuals(kabc1, type = "raw")
## $type
## [1] "raw"
## 
## $cov
##        hm     nr     wo     gc     tr     sm     ma     ps
## hm  0.000                                                 
## nr  0.820  0.000                                          
## wo  0.462  2.751  0.000                                   
## gc -0.513 -0.836 -0.711  0.000                            
## tr -0.631 -0.519 -0.602  0.415  0.000                     
## sm  0.397 -0.452 -0.863 -0.097  0.212  0.000              
## ma  0.437  0.069 -0.199  0.186  0.022  0.131  0.000       
## ps -0.345 -0.659 -0.263  0.550  0.530  0.229 -0.289  0.000
lavaan::residuals(kabc1, type = "standardized.mplus")
## $type
## [1] "standardized.mplus"
## 
## $cov
##        hm     nr     wo     gc     tr     sm     ma     ps
## hm  0.000                                                 
## nr  2.062  0.000                                          
## wo  1.026  6.218  0.000                                   
## gc -1.231 -2.727 -1.952  0.000                            
## tr -2.200 -2.364 -2.355  1.379  0.000                     
## sm  0.723 -1.188 -1.995 -0.210  0.596  0.000              
## ma  1.086  0.237 -0.601  0.544  0.089  0.313  0.000       
## ps -1.241 -3.422 -1.037  1.833  2.178  0.675 -1.375  0.000
lavaan::residuals(kabc1, type = "cor.bollen")
## $type
## [1] "cor.bollen"
## 
## $cov
##        hm     nr     wo     gc     tr     sm     ma     ps
## hm  0.000                                                 
## nr  0.101  0.000                                          
## wo  0.047  0.397  0.000                                   
## gc -0.056 -0.130 -0.091  0.000                            
## tr -0.069 -0.080 -0.077  0.057  0.000                     
## sm  0.028 -0.045 -0.071 -0.009  0.019  0.000              
## ma  0.046  0.010 -0.025  0.025  0.003  0.011  0.000       
## ps -0.034 -0.092 -0.030  0.068  0.066  0.018 -0.035  0.000