In this lab you will learn to:
Important constraint for this lab:
You are not allowed to add paths “because MI says so”. Each change needs a short substantive rationale.
We simulate data from a “true” model and then fit a misspecified model to create diagnostic signals.
True DGP:
lifeSatisfaction depends on attachment, selfEsteem, parentalSupport, salaryselfEsteem depends on parentalSupport and attachmentattachment covaries with parentalSupportN <- 483
m_true <- "
lifeSatisfaction ~ .05*attachment + .25*selfEsteem + .40*parentalSupport + .30*salary
selfEsteem ~ .40*parentalSupport + .20*attachment
attachment ~~ .30*parentalSupport
"
dat <- simulateData(m_true, sample.nobs = N, seed = 2026)
summary(dat) lifeSatisfaction selfEsteem attachment parentalSupport
Min. :-3.7002 Min. :-3.1965 Min. :-2.66785 Min. :-2.9075
1st Qu.:-0.8613 1st Qu.:-0.7769 1st Qu.:-0.72205 1st Qu.:-0.7266
Median :-0.0683 Median : 0.0113 Median : 0.00539 Median :-0.0732
Mean :-0.0308 Mean :-0.0184 Mean :-0.03731 Mean :-0.0314
3rd Qu.: 0.7516 3rd Qu.: 0.7091 3rd Qu.: 0.64163 3rd Qu.: 0.6940
Max. : 3.4794 Max. : 3.0854 Max. : 2.80907 Max. : 3.1298
salary
Min. :-2.9048
1st Qu.:-0.6525
Median :-0.0525
Mean :-0.0287
3rd Qu.: 0.6024
Max. : 2.4550
We omit:
lifeSatisfactionattachment ~~ parentalSupportAnswer in 3–5 sentences:
Question
# Play with the different 'type of residuals'
# 'cor', 'cor.bollen', 'cor.bentler', 'raw'
res_cov <- lavResiduals(fit0)
# res_cov$resid is S - Sigma_hat
res_cov$cov lfStsf slfEst salary prntlS attchm
lifeSatisfaction -0.005
selfEsteem -0.005 0.000
salary -0.008 -0.018 0.000
parentalSupport 0.288 0.000 0.000 0.000
attachment 0.076 0.000 0.000 0.000 0.000
Tasks
Compute MI and inspect the top candidates.
mi <- modificationIndices(fit0, sort. = TRUE)
head(mi[, c("lhs","op","rhs","mi","epc","sepc.all")], 12) lhs op rhs mi epc sepc.all
19 lifeSatisfaction ~ parentalSupport 67.193 0.428 0.351
18 lifeSatisfaction ~~ selfEsteem 58.870 -0.764 -0.773
27 parentalSupport ~ lifeSatisfaction 45.447 0.263 0.321
21 selfEsteem ~ lifeSatisfaction 41.326 -0.469 -0.545
20 lifeSatisfaction ~ attachment 4.161 0.099 0.082
23 salary ~ lifeSatisfaction 0.407 -0.045 -0.059
22 selfEsteem ~ salary 0.204 -0.021 -0.018
31 attachment ~ lifeSatisfaction 0.142 -0.014 -0.017
28 parentalSupport ~ selfEsteem 0.126 0.610 0.640
24 salary ~ selfEsteem 0.126 -0.013 -0.014
32 attachment ~ selfEsteem 0.005 -0.895 -0.925
11 parentalSupport ~~ attachment 0.000 0.000 NA
Tasks
Write a one-sentence justification.
Common modifications include:
~~)~)Create m1 below and refit.
lfStsf slfEst salary prntlS attchm
lifeSatisfaction -0.003
selfEsteem -0.003 0.000
salary -0.005 -0.009 0.000
parentalSupport 0.364 0.000 0.021 0.000
attachment 0.098 0.000 0.006 0.000 0.000
Interpretation questions
Repeat Exercise 5 one more time:
m2 by adding one additional parameter (only one) to m1fit1 vs fit2Task
Document your respecification path:
Fit the model that generated the data. This is not something you can do in real life, but it calibrates your intuition.
fit_true <- sem(m_true, data = dat, meanstructure = TRUE)
fitMeasures(fit_true, c("chisq","df","cfi","tli","rmsea","srmr"))chisq df cfi tli rmsea srmr
7.76 10.00 1.00 1.01 0.00 0.03
Questions