# principles and practice of sem, 5th ed.
# rex b. kline, guilford press, 2023
# chapter 17, table 17.1, analysis 1
# proportionality-constrained loadings and
# alternative test statistics in a small-sample cfa
# (n = 103)
# 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()
v <- R.Version()
print(paste0(v$language, " version ", v$major, ".",
v$minor, " (", v$year, "-", v$month, "-", v$day, ")"))
library(lavaan)
library(semTools)
# get citation information
citation("lavaan", auto = TRUE)
citation("semTools", auto = TRUE)
# input the correlations in lower diagnonal form
sabatelliLower.cor <- '
1.000
.740 1.000
.265 .422 1.000
.305 .401 .791 1.000
.315 .351 .662 .587 1.000 '
# name the variables and convert to full correlation matrix
sabatelli.cor <- lavaan::getCov(sabatelliLower.cor, names = c("problems",
"intimacy", "father", "mother", "both"))
# add the standard deviations and convert to covariances
sabatelli.cov <- lavaan::cor2cov(sabatelli.cor, sds = c(32.936,22.749,
13.390,13.679,14.382))
# display correlations and covariances
sabatelli.cor
sabatelli.cov
# maccallum-rmsea for whole model
# exact fit test
# power at N = 103
semTools::findRMSEApower(0, .05, 5, 103, .05, 1)
# minimum N for power at least .90
semTools::findRMSEAsamplesize(0, .05, 5, .90, .05, 1)
# analysis with constrained loadings
# for indicators of marital adjustment
# model df = 5
# standard deviations for both indicators
# of the marital factor are listed next
# intimacy, sd = 22.749
# problems, sd = 32.936
# ratio = 22.749/32.936 = .691
# specify model with constrained loadings
# for problems, intimacy
proportional.model <- '
# common factors
# loading for intimacy constrained to equal .691
Marital =~ 1*problems + .691*intimacy
FOE =~ father + mother + both '
# fit respecified model to data
proportional <- lavaan::sem(proportional.model, sample.cov = sabatelli.cov,
sample.nobs = 103)
lavaan::summary(proportional, fit.measures = TRUE, standardized = TRUE,
rsquare = TRUE)
lavaan::parameterEstimates(proportional)
lavaan::standardizedSolution(proportional)
#covariance residuals
lavaan::residuals(proportional, type = "raw")
# standardized residuals
# the computer was unable to calculate all
# standardized residuals (i.e., NA in output)
lavaan::residuals(proportional, type = "standardized.mplus")
# normalized residuals and correlation residuals
# no apparent problems in these results
lavaan::residuals(proportional, type = "normalized")
lavaan::residuals(proportional, type = "cor.bollen")
# maydeu-olivares, shi, & rosseel (2018)
# exact-fit and close-fit tests based on
# correlations residuals
# population value of null hypothesis
# for close fit tests <= .05
# bollen-type correlation residuals
# test statistic is crmr
lavaan::lavResiduals(proportional, type = "cor.bollen", summary = TRUE)
# bentler-type correlation residuals
# test statistic is srmr
lavaan::lavResiduals(proportional, type = "cor.bentler", summary = TRUE)