# principles and practice of sem, 5th ed. # rex b. kline, guilford press, 2023 # chapter 8, table 8.1, analysis 2 # compute partial correlations for implied conditional # independencies of the union basis set in table 6.4 # and compute the d-sep test for 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(semTools) library(lavaan) library(piecewiseSEM) library(psych) # packages semTools and lavaan are used to generate raw # scores for analyses in packages piecewiseSEM and psych # get citation information citation("semTools", auto = TRUE) citation("lavaan", auto = TRUE) citation("piecewiseSEM", auto = TRUE) citation("psych", auto = TRUE) # generate raw scores with descriptive statistics that # exactly match those from the summary data in table 4.3 # reuses syntax from analysis 1 ("roth-generate-scores.r") to # avoid reading in an external raw data file roth.cor <- matrix(c(1.00, -.03, .39, -.05, -.08, -.03, 1.00, .07, -.23, -.16, .39, .07, 1.00, -.13, -.29, -.05, -.23, -.13, 1.00, .34, -.08, -.16, -.29, .34, 1.00), ncol = 5, nrow = 5) roth.sd <- c(66.5, 38.0, 18.4, 33.5, 62.48) roth.cov <- diag(roth.sd) %*% roth.cor %*% diag(roth.sd) c = 372/373 roth.cov = c * roth.cov roth.data <- semTools::kd(roth.cov, 373, type = "exact") names(roth.data) <- c("exercise", "hardy", "fitness", "stress", "illness") roth.data <- transform(roth.data, exercise = exercise + 40.9) roth.data <- transform(roth.data, fitness = fitness + 67.1) roth.data <- transform(roth.data, stress = stress + 24.0) roth.data <- transform(roth.data, illness = illness + 71.67) # define the model as a series of regression equations # exercise and hardy covary roth.model <- piecewiseSEM::psem( lm(illness ~ stress + fitness, data = roth.data), lm(fitness ~ exercise, data = roth.data), lm(stress ~ hardy, data = roth.data), exercise %~~% hardy, data = roth.data ) # list union basis set # these results duplicate those in table 6.4 piecewiseSEM::basisSet(roth.model) # p values from significance tests of partial correlations # for each implied conditional independence in the union basis set piecewiseSEM::dSep(roth.model, conditioning = TRUE, .progressBar = FALSE) # piecewise goodness-of-fit test for all implied conditional # indepenedencies of the union basis set piecewiseSEM::fisherC(roth.model, .progressBar = FALSE) # generate values of sample partial correlations # stress ~ exercise + hardy pr1 <- psych::partial.r(roth.data, c("exercise","stress"), c("hardy")) print(pr1, digits = 3) # illness ~ exercise + stress + fitness pr2 <- psych::partial.r(roth.data, c("illness","exercise"), c("stress", "fitness")) print(pr2, digits = 3) # fitness ~ hardy + exercise pr3 <- psych::partial.r(roth.data, c("fitness","hardy"), c("exercise")) print(pr3, digits = 3) # illness ~ hardy + stress + fitness pr4 <- psych::partial.r(roth.data, c("illness","hardy"), c("stress", "fitness")) print(pr4, digits = 3) # fitness ~ stress + hardy + exercise pr5 <- psych::partial.r(roth.data, c("fitness","stress"), c("hardy", "exercise")) print(pr5, digits = 3)