# principles and practice of sem, 5th ed. # rex b. kline, guilford press, 2023 # chapter 9, table 9.1, analysis 2 # global estimation of the covariance and mean structures # in the roth et al. (1989) parametric path model of illness # 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) # get citation information citation("lavaan", auto = TRUE) # input the correlations in lower diagnonal form rothLower.cor <- ' 1.00 -.03 1.00 .39 .07 1.00 -.05 -.23 -.13 1.00 -.08 -.16 -.29 .34 1.00 ' # name the variables and convert to full correlation matrix roth.cor <- lavaan::getCov(rothLower.cor, names = c("exercise", "hardy", "fitness", "stress", "illness")) # display the correlations roth.cor # add the standard deviations and convert to covariances roth.cov <- lavaan::cor2cov(roth.cor, sds = c(66.50,38.00,18.40,33.50,62.48)) roth.mean <- c(40.9,0,67.1,24.0,71.67) # display the covariances and means roth.cov roth.mean # specify path model roth.model <- ' # regressions fitness ~ a*exercise stress ~ c*hardy illness ~ b*fitness + d*stress # unanalyzed association between exercise and hardy # automatically specified # specify indirect effects on illness ab := a*b cd := c*d ' # fit model to sample covariance matrix and means, N = 373 # variances and covariance of measured exogenous # variables are free parameters # variances calculated with N - 1 in the denominator instead of N # default information matrix is expected # meanstructure = TRUE specifies that intercepts for endogenous # variables and means for exogenous variables are estimated roth <- lavaan::sem(roth.model, sample.cov = roth.cov, sample.mean = roth.mean, sample.nobs = 373, fixed.x = FALSE, sample.cov.rescale = FALSE, meanstructure = TRUE) # check for negative error variances # TRUE in output means no negative variances lavaan::lavInspect(roth, add.labels = TRUE, "post.check") # request output # intercepts and means are the only new results # values for exercise and hardy (exogenous) listed as # intercepts are actually means lavaan::summary(roth, fit.measures = TRUE, rsquare = TRUE) # generate predicted covariance matrix, predicted means # df = 0 for mean structure so observed = predicted means lavaan::fitted(roth)