Structural Equation Modeling: A Practical Tutorial with R
What SEM is, why it matters, and how to fit a model using lavaan
R
Statistics
Structural Equation Modeling
Latent Variables
Lavaan
Data Science
Author
Nivedita Bhadra
Published
May 28, 2026
1 What is Structural Equation Modeling?
Structural Equation Modeling, usually called SEM, is a statistical framework used to study relationships among multiple variables at the same time.
In ordinary regression, we usually ask a question like:
Does X predict Y? — for example, does stress predict depression score?
SEM lets us ask a broader, more realistic question:
How do several observed and unobserved variables relate to each other simultaneously? Does socioeconomic status influence stress, and does stress then influence depression? Are stress and depression measured through several questionnaire items rather than one direct variable? Is the effect of socioeconomic status on depression partly mediated through stress?
SEM is useful because many scientific concepts are not directly observed. Variables such as intelligence, resilience, depression, socioeconomic status, anxiety, wellbeing, cognitive ability, and biological vulnerability are often latent constructs — we observe them indirectly, through questionnaire items, test scores, biomarkers, or behavioral measures.
SEM combines two ideas:
Measurement model — describes how observed variables measure latent variables.
Structural model — describes how latent or observed variables relate to each other.
A simple way to remember SEM:
SEM = factor analysis + regression/path analysis
The lavaan package is one of the most widely used open-source R packages for SEM. It supports confirmatory factor analysis, SEM, latent growth models, and related latent variable models (Rosseel, 2012, Journal of Statistical Software).
2 Why is SEM important?
SEM matters because many real-world research questions aren’t simple one-variable-to-one-variable problems. In psychology, psychiatry, education, epidemiology, sociology, genetics, public health, and economics, researchers routinely work with complex systems, and SEM helps model them in a structured way.
Suppose we’re studying psychological resilience. We might believe that family support improves resilience, resilience reduces depression, socioeconomic stress reduces resilience, depression is measured by several symptoms, and resilience is measured by several questionnaire items. A basic regression model can only test one piece of this system at a time — SEM lets us test the full hypothesized structure at once.
SEM is especially useful when we want to model latent variables, account for measurement error, test mediation, test direct and indirect effects, combine multiple regression equations, test whether a theoretical model fits the data, or compare competing theoretical models. This is why SEM is common in fields where theoretical structure matters as much as prediction.
3 Observed Variables and Latent Variables
In SEM, variables are usually divided into two types.
3.1 Observed Variables
Observed variables are directly measured in the dataset — age, sex, income, PHQ-9 item scores, test scores, biomarker values, and questionnaire responses are all examples. In path diagrams, observed variables are usually shown as rectangles.
3.2 Latent Variables
Latent variables are not directly observed — they’re inferred from multiple observed indicators. Depression, anxiety, resilience, cognitive ability, socioeconomic status, inflammation, and wellbeing are common examples. In path diagrams, latent variables are usually shown as circles or ovals.
For example, depression might be measured using several questionnaire items:
depression =~ dep1 + dep2 + dep3 + dep4
Here, depression is a latent variable, and dep1, dep2, dep3, and dep4 are its observed indicators. In lavaan, the operator =~ defines a latent variable. The official lavaan tutorial describes three core operators: =~ for latent variable definitions, ~ for regressions, and ~~ for variances/covariances.
4 The Two Parts of SEM
4.1 Measurement Model
The measurement model asks:
Are my observed variables good indicators of the latent construct?
This says depression is measured by three depression items, and resilience is measured by three resilience items. This part of SEM is closely related to Confirmatory Factor Analysis (CFA), used when we already have a hypothesis about which observed variables measure which latent variables — lavaan provides the cfa() function for this purpose.
4.2 Structural Model
The structural model asks:
How are the latent variables related to each other?
This says depression is predicted by resilience and stress, and resilience is predicted by social support. The structural part is essentially a system of regression models.
5 SEM Syntax in lavaan
The basic lavaan syntax is very readable.
Latent variable definition:
latent_variable =~ item1 + item2 + item3
Example: depression =~ dep1 + dep2 + dep3
Regression path:
outcome ~ predictor
Example: depression ~ stress + resilience
Covariance:
var1 ~~ var2
Example: stress ~~ social_support
Variance:
var1 ~~ var1
Example: stress ~~ stress
6 A Simple SEM Example
Let’s build a worked example around three latent constructs: Stress, Resilience, and Depression, each measured by three observed questionnaire items.
We hypothesize that stress increases depression, resilience reduces depression, stress reduces resilience, and resilience partially mediates the effect of stress on depression. The conceptual model is:
This is lavaan 0.7-2
lavaan is FREE software! Please report any bugs.
A data.frame: 6 × 9
stress1
stress2
stress3
resil1
resil2
resil3
dep1
dep2
dep3
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
1
-0.7767752
-0.6481348
-0.77595113
-0.22114415
0.5982737
-0.102528898
-0.4598761
-0.94150853
-1.43572002
2
-0.3070449
-0.0426553
0.02256535
-0.67499896
-1.1793024
-0.351837840
-0.6746907
0.21788373
-0.96182442
3
0.8861274
0.8203012
1.12103167
-0.54560701
-0.9125343
0.306268174
1.2368075
0.05049758
0.19536724
4
0.3072342
0.6589697
-0.15013607
0.17356204
0.2572333
-0.004627744
-0.7595522
0.41896327
-0.06974591
5
0.5515722
0.1775694
0.42611280
0.02181441
-0.6751701
-1.955223221
-0.5580200
-0.29196672
-1.45021286
6
2.2229374
0.8929113
1.35330993
-0.76188637
-0.7179487
0.041845017
2.5151611
1.92810266
2.51116992
stress1 stress2 stress3 resil1
Min. :-2.68041 Min. :-2.691356 Min. :-2.64489 Min. :-2.82284
1st Qu.:-0.54070 1st Qu.:-0.543447 1st Qu.:-0.53635 1st Qu.:-0.64442
Median : 0.06657 Median :-0.029942 Median : 0.04875 Median : 0.01097
Mean : 0.05116 Mean :-0.007807 Mean : 0.04066 Mean :-0.02437
3rd Qu.: 0.57855 3rd Qu.: 0.524629 3rd Qu.: 0.61250 3rd Qu.: 0.53320
Max. : 2.78049 Max. : 2.680151 Max. : 3.15869 Max. : 2.26858
resil2 resil3 dep1 dep2
Min. :-2.42576 Min. :-3.19028 Min. :-3.012669 Min. :-2.59815
1st Qu.:-0.59795 1st Qu.:-0.66951 1st Qu.:-0.761669 1st Qu.:-0.62917
Median : 0.04993 Median :-0.02788 Median : 0.006298 Median : 0.01076
Mean :-0.01127 Mean :-0.03598 Mean : 0.037102 Mean : 0.04762
3rd Qu.: 0.52862 3rd Qu.: 0.59763 3rd Qu.: 0.785262 3rd Qu.: 0.76276
Max. : 2.48716 Max. : 2.97850 Max. : 3.457041 Max. : 3.43147
dep3
Min. :-3.66353
1st Qu.:-0.84296
Median : 0.07153
Mean : 0.06997
3rd Qu.: 0.97918
Max. : 4.09965
This simulates 500 observations of three correlated latent traits, each expressed through three noisy observed indicators — a clean synthetic dataset to fit an SEM against. head() and summary() confirm the data is roughly standardized (means near 0, no obvious outliers).
8 Define the SEM Model
# ------------------------------------------------------------# 2. Define SEM model# ------------------------------------------------------------model_sem <-' # Measurement model stress =~ stress1 + stress2 + stress3 resilience =~ resil1 + resil2 + resil3 depression =~ dep1 + dep2 + dep3 # Structural model resilience ~ a * stress depression ~ b * resilience + c * stress # Indirect, direct, and total effects indirect := a * b direct := c total := c + (a * b)'
Reading this line by line:
stress =~ stress1 + stress2 + stress3 — the latent variable stress is measured by three observed items.
resilience ~ a * stress — stress predicts resilience, with the path coefficient labeled a.
depression ~ b * resilience + c * stress — depression is predicted by both resilience and stress; the resilience → depression path is labeled b, and the direct stress → depression path is labeled c.
indirect := a * b — the indirect (mediated) effect of stress on depression, running through resilience.
total := c + (a * b) — the total effect: direct plus indirect.
9 Fit the SEM Model
# ------------------------------------------------------------# 3. Fit the model# ------------------------------------------------------------fit_sem <-sem( model_sem,data = data_sem,meanstructure =TRUE)summary( fit_sem,fit.measures =TRUE,standardized =TRUE,rsquare =TRUE)
lavaan NOTE:
Standard errors and confidence intervals of the (nonlinear) defined (:=)
parameters are based on the first-order delta method; for strongly
nonlinear definitions, se.def = "mc" (Monte Carlo) or se = "bootstrap" may
be more accurate.
$header
$lavaan.version
'0.7-2'
$sam.approach
FALSE
$optim.method
'nlminb'
$optim.iterations
34
$optim.converged
TRUE
$optim
$estimator
'ML'
$estimator.args
$optim.method
'nlminb'
$npar
30
$eq.constraints
FALSE
$nrow.ceq.jac
0
$nrow.cin.jac
0
$nrow.con.jac
0
$con.jac.rank
0
$data
$ngroups
1
$nobs
500
$test
$standard =
$test
'standard'
$stat
39.5933180430763
$stat.group
39.5933180430763
$df
24
$refdistr
'chisq'
$pvalue
0.023638187618621
$fit
npar
30
fmin
0.0395933180430763
chisq
39.5933180430763
df
24
pvalue
0.023638187618621
baseline.chisq
4010.69045035666
baseline.df
36
baseline.pvalue
0
cfi
0.996076847181476
tli
0.994115270772214
logl
-4261.75022147873
unrestricted.logl
-4241.95356245719
aic
8583.50044295747
bic
8709.93868591013
ntotal
500
bic2
8614.71683163778
rmsea
0.0360477900883863
rmsea.ci.lower
0.0133206537558792
rmsea.ci.upper
0.0554785467010791
rmsea.ci.level
0.9
rmsea.pvalue
0.872609329442447
rmsea.close.h0
0.05
rmsea.notclose.pvalue
2.92071859358351e-05
rmsea.notclose.h0
0.08
srmr
0.0195584346342506
gfi
0.994230146309336
gfi.ci.lower
0.985281597136529
gfi.ci.upper
0.999811174122434
gfi.ci.level
0.9
$pe
A data.frame: 47 × 11
lhs
op
rhs
label
exo
est
se
z
pvalue
std.lv
std.all
<chr>
<chr>
<chr>
<chr>
<int>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
1
stress
=~
stress1
0
1.000000000
0.00000000
NA
NA
0.743305042
0.868605970
2
stress
=~
stress2
0
0.888712566
0.03965218
22.4127048
0.000000e+00
0.660584531
0.807109561
3
stress
=~
stress3
0
1.165333138
0.04332610
26.8967905
0.000000e+00
0.866197997
0.917815829
4
resilience
=~
resil1
0
1.000000000
0.00000000
NA
NA
0.771457415
0.896166093
5
resilience
=~
resil2
0
0.851920295
0.03685346
23.1164239
0.000000e+00
0.657220229
0.803459938
6
resilience
=~
resil3
0
1.123935553
0.04011596
28.0171692
0.000000e+00
0.867068417
0.905885416
7
depression
=~
dep1
0
1.000000000
0.00000000
NA
NA
1.115486326
0.939423104
8
depression
=~
dep2
0
0.852686146
0.02485828
34.3018961
0.000000e+00
0.951159737
0.891874563
9
depression
=~
dep3
0
1.146769075
0.02726355
42.0623568
0.000000e+00
1.279205223
0.950922084
10
resilience
~
stress
a
0
-0.536162652
0.04798759
-11.1729444
0.000000e+00
-0.516596762
-0.516596762
11
depression
~
resilience
b
0
-0.638717896
0.05641726
-11.3213206
0.000000e+00
-0.441729894
-0.441729894
12
depression
~
stress
c
0
0.727534488
0.05968082
12.1904241
0.000000e+00
0.484793081
0.484793081
13
stress1
~~
stress1
0
0.179796776
0.01664951
10.7989246
0.000000e+00
0.179796776
0.245523668
14
stress2
~~
stress2
0
0.233500062
0.01801124
12.9641268
0.000000e+00
0.233500062
0.348574156
15
stress3
~~
stress3
0
0.140384235
0.01830990
7.6671204
1.754152e-14
0.140384235
0.157614104
16
resil1
~~
resil1
0
0.145902412
0.01563347
9.3326929
0.000000e+00
0.145902412
0.196886334
17
resil2
~~
resil2
0
0.237165208
0.01806223
13.1304497
0.000000e+00
0.237165208
0.354452128
18
resil3
~~
resil3
0
0.164328886
0.01895948
8.6673739
0.000000e+00
0.164328886
0.179371612
19
dep1
~~
dep1
0
0.165647777
0.01695952
9.7672442
0.000000e+00
0.165647777
0.117484232
20
dep2
~~
dep2
0
0.232658848
0.01803935
12.8972957
0.000000e+00
0.232658848
0.204559764
21
dep3
~~
dep3
0
0.173267305
0.02052209
8.4429653
0.000000e+00
0.173267305
0.095747191
22
stress
~~
stress
0
0.552502385
0.04651494
11.8779564
0.000000e+00
1.000000000
1.000000000
23
resilience
~~
resilience
0
0.436318467
0.03668041
11.8951349
0.000000e+00
0.733127786
0.733127786
24
depression
~~
depression
0
0.433759482
0.03669715
11.8199764
0.000000e+00
0.348594459
0.348594459
25
stress1
~1
0
0.051164260
0.03827007
1.3369262
1.812467e-01
0.051164260
0.059789157
26
stress2
~1
0
-0.007807425
0.03660251
-0.2133030
8.310907e-01
-0.007807425
-0.009539199
27
stress3
~1
0
0.040657971
0.04220624
0.9633167
3.353886e-01
0.040657971
0.043080830
28
resil1
~1
0
-0.024374481
0.03849802
-0.6331359
5.266449e-01
-0.024374481
-0.028314698
29
resil2
~1
0
-0.011269369
0.03658152
-0.3080618
7.580353e-01
-0.011269369
-0.013776944
30
resil3
~1
0
-0.035980507
0.04280506
-0.8405667
4.005907e-01
-0.035980507
-0.037591286
31
dep1
~1
0
0.037102437
0.05310287
0.6986898
4.847459e-01
0.037102437
0.031246359
32
dep2
~1
0
0.047620784
0.04769410
0.9984627
3.180550e-01
0.047620784
0.044652611
33
dep3
~1
0
0.069974908
0.06016034
1.1631401
2.447726e-01
0.069974908
0.052017209
37
indirect
:=
a*b
indirect
0
0.342456681
0.04061961
8.4308214
0.000000e+00
0.228196233
0.228196233
38
direct
:=
c
direct
0
0.727534488
0.05968082
12.1904241
0.000000e+00
0.484793081
0.484793081
39
total
:=
c+(a*b)
total
0
1.069991169
0.06169700
17.3426763
0.000000e+00
0.712989314
0.712989314
40
stress1
r2
stress1
0
0.754476332
NA
NA
NA
NA
NA
41
stress2
r2
stress2
0
0.651425844
NA
NA
NA
NA
NA
42
stress3
r2
stress3
0
0.842385896
NA
NA
NA
NA
NA
43
resil1
r2
resil1
0
0.803113666
NA
NA
NA
NA
NA
44
resil2
r2
resil2
0
0.645547872
NA
NA
NA
NA
NA
45
resil3
r2
resil3
0
0.820628388
NA
NA
NA
NA
NA
46
dep1
r2
dep1
0
0.882515768
NA
NA
NA
NA
NA
47
dep2
r2
dep2
0
0.795440236
NA
NA
NA
NA
NA
48
dep3
r2
dep3
0
0.904252809
NA
NA
NA
NA
NA
49
resilience
r2
resilience
0
0.266872214
NA
NA
NA
NA
NA
50
depression
r2
depression
0
0.651405541
NA
NA
NA
NA
NA
The sem() function fits the structural equation model by maximum likelihood; standardized = TRUE in summary() requests standardized estimates alongside the raw ones, which are usually easier to interpret. The fit converged normally (NLMINB optimizer, 34 iterations, ML estimator, 30 free parameters, N = 500).
Global fit statistics:
Statistic
Value
\(\chi^2\)
39.593
df
24
p-value
0.024
CFI
0.996
TLI
0.994
RMSEA
0.036 (90% CI: 0.013–0.055)
SRMR
0.020
AIC
8583.500
BIC
8709.939
Parameter estimates (unstandardized):
Path
Label
Estimate
SE
z
p
stress =~ stress1
1.000 (fixed)
—
—
—
stress =~ stress2
0.889
0.040
22.41
<.001
stress =~ stress3
1.165
0.043
26.90
<.001
resilience =~ resil1
1.000 (fixed)
—
—
—
resilience =~ resil2
0.852
0.037
23.12
<.001
resilience =~ resil3
1.124
0.040
28.02
<.001
depression =~ dep1
1.000 (fixed)
—
—
—
depression =~ dep2
0.853
0.025
34.30
<.001
depression =~ dep3
1.147
0.027
42.06
<.001
resilience ~ stress
a
−0.536
0.048
−11.17
<.001
depression ~ resilience
b
−0.639
0.056
−11.32
<.001
depression ~ stress
c
0.728
0.060
12.19
<.001
indirect (a*b)
0.342
0.041
8.43
<.001
direct (c)
0.728
0.060
12.19
<.001
total (c + a*b)
1.070
0.062
17.34
<.001
The first indicator of each latent factor (stress1, resil1, dep1) is fixed to a loading of 1.000 — this is lavaan’s default identification constraint, which sets the scale of the latent variable to match that indicator, not a result being estimated.
R² for endogenous variables:
Variable
R²
resilience
0.267
depression
0.651
stress1
0.754
stress2
0.651
stress3
0.842
resil1
0.803
resil2
0.646
resil3
0.821
dep1
0.883
dep2
0.795
dep3
0.904
10 Understanding the Output
10.1 Factor Loadings
Factor loadings show how strongly each observed item measures its latent construct. For example, if the standardized loading of stress1 is 0.85, that means stress1 is a strong indicator of the latent stress factor. A rough interpretation guide:
Standardized loading
Interpretation
~0.30
weak
~0.50
moderate
≥0.70
strong
These are rough guidelines only — interpretation depends on the field and the measurement instrument.
10.2 Regression Paths
The structural paths tell us how latent variables predict each other:
A negative standardized coefficient from stress to resilience means higher stress is associated with lower resilience. A negative coefficient from resilience to depression means higher resilience is associated with lower depression. A positive coefficient from stress to depression means higher stress is associated with higher depression — consistent with the fitted estimates above.
10.3 R-Squared Values
R² tells us how much variance is explained in each endogenous variable. In this model, roughly 27% of the variance in resilience is explained by stress, and roughly 65% of the variance in depression is explained jointly by stress and resilience.
11 Model Fit Indices
SEM doesn’t only estimate coefficients — it also asks:
Does the proposed model reproduce the observed covariance structure reasonably well?
This is one of the key differences between SEM and ordinary regression. Common fit indices:
11.1 Chi-Square Test
The chi-square test evaluates exact model fit. A significant chi-square suggests the model-implied covariance matrix differs from the observed covariance matrix. However, chi-square is sensitive to sample size — with large samples, even small misfit can become statistically significant.
11.2 CFI: Comparative Fit Index
CFI compares the proposed model to a baseline (null) model. Rough guidelines: CFI > 0.90 is acceptable, CFI > 0.95 is good.
11.3 TLI: Tucker-Lewis Index
Similar to CFI, but penalizes model complexity. Rough guidelines: TLI > 0.90 is acceptable, TLI > 0.95 is good.
11.4 RMSEA: Root Mean Square Error of Approximation
RMSEA measures approximate fit. Rough guidelines: RMSEA < 0.08 is acceptable, RMSEA < 0.05 is good.
11.5 SRMR: Standardized Root Mean Square Residual
SRMR measures the average standardized difference between observed and model-predicted correlations. Rough guideline: SRMR < 0.08 is acceptable.
These cutoffs should not be applied mechanically — they’re guidelines, not universal rules.
By every index except the (sample-size-sensitive) chi-square p-value, this model fits very well: CFI and TLI are both well above 0.95, and RMSEA and SRMR are both comfortably below their “good fit” thresholds.
12 Visualize the SEM Model
# ------------------------------------------------------------# 4. Plot the SEM model# ------------------------------------------------------------semPaths( fit_sem,what ="std",layout ="tree",edge.label.cex =1.0,sizeMan =6,sizeLat =8,residuals =FALSE,intercepts =FALSE,nCharNodes =0)
This produces a path diagram. In the diagram, circles represent latent variables, rectangles represent observed variables, arrows represent regression or measurement paths, and the numbers on the arrows are standardized coefficients.
For this fitted model, the diagram would show: stress loading onto stress1/stress2/stress3 at roughly 0.87 / 0.81 / 0.92; resilience loading onto its three indicators at roughly 0.90 / 0.80 / 0.91; depression loading onto its three indicators at roughly 0.94 / 0.89 / 0.95; a stress → resilience path around −0.52; a resilience → depression path around −0.44; and a stress → depression path around 0.48.
13 Mediation in SEM
One of the most useful applications of SEM is mediation analysis. In our example:
meaning stress may affect depression indirectly, through resilience. The indirect effect is \(\text{indirect} := a \times b\), where \(a\) is the effect of stress on resilience and \(b\) is the effect of resilience on depression. The total effect is \(\text{total} := \text{direct} + \text{indirect}\).
parameterEstimates( fit_sem,standardized =TRUE)
A lavaan.data.frame: 39 × 12
lhs
op
rhs
label
est
se
z
pvalue
ci.lower
ci.upper
std.lv
std.all
<chr>
<chr>
<chr>
<chr>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
stress
=~
stress1
1.000000000
0.00000000
NA
NA
1.00000000
1.00000000
0.743305042
0.868605970
stress
=~
stress2
0.888712566
0.03965218
22.4127048
0.000000e+00
0.81099572
0.96642941
0.660584531
0.807109561
stress
=~
stress3
1.165333138
0.04332610
26.8967905
0.000000e+00
1.08041554
1.25025074
0.866197997
0.917815829
resilience
=~
resil1
1.000000000
0.00000000
NA
NA
1.00000000
1.00000000
0.771457415
0.896166093
resilience
=~
resil2
0.851920295
0.03685346
23.1164239
0.000000e+00
0.77968883
0.92415176
0.657220229
0.803459938
resilience
=~
resil3
1.123935553
0.04011596
28.0171692
0.000000e+00
1.04530972
1.20256138
0.867068417
0.905885416
depression
=~
dep1
1.000000000
0.00000000
NA
NA
1.00000000
1.00000000
1.115486326
0.939423104
depression
=~
dep2
0.852686146
0.02485828
34.3018961
0.000000e+00
0.80396481
0.90140748
0.951159737
0.891874563
depression
=~
dep3
1.146769075
0.02726355
42.0623568
0.000000e+00
1.09333350
1.20020465
1.279205223
0.950922084
resilience
~
stress
a
-0.536162652
0.04798759
-11.1729444
0.000000e+00
-0.63021660
-0.44210871
-0.516596762
-0.516596762
depression
~
resilience
b
-0.638717896
0.05641726
-11.3213206
0.000000e+00
-0.74929370
-0.52814210
-0.441729894
-0.441729894
depression
~
stress
c
0.727534488
0.05968082
12.1904241
0.000000e+00
0.61056223
0.84450674
0.484793081
0.484793081
stress1
~~
stress1
0.179796776
0.01664951
10.7989246
0.000000e+00
0.14716434
0.21242921
0.179796776
0.245523668
stress2
~~
stress2
0.233500062
0.01801124
12.9641268
0.000000e+00
0.19819867
0.26880145
0.233500062
0.348574156
stress3
~~
stress3
0.140384235
0.01830990
7.6671204
1.754152e-14
0.10449748
0.17627099
0.140384235
0.157614104
resil1
~~
resil1
0.145902412
0.01563347
9.3326929
0.000000e+00
0.11526137
0.17654346
0.145902412
0.196886334
resil2
~~
resil2
0.237165208
0.01806223
13.1304497
0.000000e+00
0.20176389
0.27256653
0.237165208
0.354452128
resil3
~~
resil3
0.164328886
0.01895948
8.6673739
0.000000e+00
0.12716899
0.20148878
0.164328886
0.179371612
dep1
~~
dep1
0.165647777
0.01695952
9.7672442
0.000000e+00
0.13240773
0.19888783
0.165647777
0.117484232
dep2
~~
dep2
0.232658848
0.01803935
12.8972957
0.000000e+00
0.19730237
0.26801533
0.232658848
0.204559764
dep3
~~
dep3
0.173267305
0.02052209
8.4429653
0.000000e+00
0.13304475
0.21348986
0.173267305
0.095747191
stress
~~
stress
0.552502385
0.04651494
11.8779564
0.000000e+00
0.46133479
0.64366999
1.000000000
1.000000000
resilience
~~
resilience
0.436318467
0.03668041
11.8951349
0.000000e+00
0.36442618
0.50821076
0.733127786
0.733127786
depression
~~
depression
0.433759482
0.03669715
11.8199764
0.000000e+00
0.36183438
0.50568458
0.348594459
0.348594459
stress1
~1
0.051164260
0.03827007
1.3369262
1.812467e-01
-0.02384370
0.12617222
0.051164260
0.059789157
stress2
~1
-0.007807425
0.03660251
-0.2133030
8.310907e-01
-0.07954703
0.06393218
-0.007807425
-0.009539199
stress3
~1
0.040657971
0.04220624
0.9633167
3.353886e-01
-0.04206473
0.12338067
0.040657971
0.043080830
resil1
~1
-0.024374481
0.03849802
-0.6331359
5.266449e-01
-0.09982922
0.05108026
-0.024374481
-0.028314698
resil2
~1
-0.011269369
0.03658152
-0.3080618
7.580353e-01
-0.08296782
0.06042908
-0.011269369
-0.013776944
resil3
~1
-0.035980507
0.04280506
-0.8405667
4.005907e-01
-0.11987688
0.04791587
-0.035980507
-0.037591286
dep1
~1
0.037102437
0.05310287
0.6986898
4.847459e-01
-0.06697728
0.14118215
0.037102437
0.031246359
dep2
~1
0.047620784
0.04769410
0.9984627
3.180550e-01
-0.04585794
0.14109951
0.047620784
0.044652611
dep3
~1
0.069974908
0.06016034
1.1631401
2.447726e-01
-0.04793719
0.18788701
0.069974908
0.052017209
stress
~1
0.000000000
0.00000000
NA
NA
0.00000000
0.00000000
0.000000000
0.000000000
resilience
~1
0.000000000
0.00000000
NA
NA
0.00000000
0.00000000
0.000000000
0.000000000
depression
~1
0.000000000
0.00000000
NA
NA
0.00000000
0.00000000
0.000000000
0.000000000
indirect
:=
a*b
indirect
0.342456681
0.04061961
8.4308214
0.000000e+00
0.26284371
0.42206965
0.228196233
0.228196233
direct
:=
c
direct
0.727534488
0.05968082
12.1904241
0.000000e+00
0.61056223
0.84450674
0.484793081
0.484793081
total
:=
c+(a*b)
total
1.069991169
0.06169700
17.3426763
0.000000e+00
0.94906726
1.19091507
0.712989314
0.712989314
The key rows of that output are the ones we already labeled in the model syntax:
Effect
Estimate
SE
z
p
indirect (a*b)
0.342
0.041
8.43
<.001
direct (c)
0.728
0.060
12.19
<.001
total (c + a*b)
1.070
0.062
17.34
<.001
This confirms both a direct effect of stress on depression and a meaningful indirect (mediated) effect through resilience — together summing to the total effect.
14 Bootstrapped Confidence Intervals for Indirect Effects
Indirect effects often have non-normal sampling distributions, so bootstrapping is commonly used for mediation inference instead of relying on the normal-theory z-test.
With 1,000 bootstrap resamples, the key structural and derived-effect estimates were essentially unchanged from the normal-theory fit, with modestly different standard errors:
Effect
Estimate
Bootstrap SE
z
p
resilience ~ stress (a)
−0.536
0.048
−11.23
<.001
depression ~ resilience (b)
−0.639
0.052
−12.35
<.001
depression ~ stress (c)
0.728
0.059
12.39
<.001
indirect (a*b)
0.342
0.039
8.71
<.001
direct (c)
0.728
0.059
12.39
<.001
total (c + a*b)
1.070
0.066
16.21
<.001
If the bootstrap confidence interval for the indirect effect does not include zero, that supports evidence for mediation — as it doesn’t here.
15 CFA Before SEM
In practice, it’s often useful to fit the measurement model alone first, before adding any structural paths.
This CFA-only fit lets all three latent factors freely covary (rather than imposing the directional structural paths), and shows essentially identical fit to the full SEM: \(\chi^2(24) = 39.59\), \(p = 0.024\), CFI = 0.996, TLI = 0.994, RMSEA = 0.036, SRMR = 0.020 — and factor loadings matching those from the full model. That agreement is a good sign: it means the structural paths we added aren’t distorting the measurement model, and the latent constructs are well identified on their own.
This checks whether the measurement structure is reasonable before adding structural paths. A good general workflow:
Check the measurement model using CFA.
Check reliability and factor loadings.
Fit the full SEM model.
Interpret direct, indirect, and total effects.
Report model fit and standardized estimates.
16 SEM Versus Regression
Regression and SEM are related, but SEM is more general.
Feature
Regression
SEM
Observed variables
Yes
Yes
Latent variables
No
Yes
Multiple outcomes
Limited
Yes
Measurement error
Usually ignored
Explicitly modeled
Mediation
Possible
Natural framework
Model fit
Usually not covariance-based
Central part of SEM
Theory testing
Limited
Strong
Regression is often enough when the research question is simple and all variables are directly observed. SEM is worth reaching for when constructs are latent, measurement error matters, several equations are needed at once, mediation is central to the question, or the theoretical structure itself is part of what’s being tested.
17 Assumptions of SEM
SEM rests on assumptions that should be considered carefully.
17.1 Correct Model Specification
The model should be theoretically justified. SEM can test whether a model is consistent with the data, but it cannot prove that the model is true — a good-fitting model is not necessarily the only good-fitting model.
17.2 Adequate Sample Size
SEM usually requires moderate to large sample sizes. There’s no single universal rule, but small samples can lead to unstable estimates, convergence problems, or unreliable fit indices.
17.3 Multivariate Normality
Classical SEM often assumes multivariate normality, especially under maximum likelihood estimation. If variables are non-normal, robust estimators can be used instead:
lavaan NOTE:
Standard errors and confidence intervals of the (nonlinear) defined (:=)
parameters are based on the first-order delta method; for strongly
nonlinear definitions, se.def = "mc" (Monte Carlo) or se = "bootstrap" may
be more accurate.
$header
$lavaan.version
'0.7-2'
$sam.approach
FALSE
$optim.method
'nlminb'
$optim.iterations
34
$optim.converged
TRUE
$optim
$estimator
'ML'
$estimator.args
$optim.method
'nlminb'
$npar
30
$eq.constraints
FALSE
$nrow.ceq.jac
0
$nrow.cin.jac
0
$nrow.con.jac
0
$con.jac.rank
0
$data
$ngroups
1
$nobs
500
$test
$standard
$test
'standard'
$stat
39.5933180430763
$stat.group
39.5933180430763
$df
24
$refdistr
'chisq'
$pvalue
0.023638187618621
$yuan.bentler.mplus
$test
'yuan.bentler.mplus'
$stat
39.1136150602653
$stat.group
39.1136150602653
$df
24
$pvalue
0.0265687152629294
$scaling.factor
1.01226434790218
$scaling.factor.h1
1.00598789331404
$scaling.factor.h0
1.00096672964353
$label
'Yuan-Bentler correction (Mplus variant)'
$trace.UGamma
24.2943443496523
$trace.UGamma2
<NA>
$scaled.test.stat
39.5933180430763
$scaled.test
'standard'
$fit
npar
30
fmin
0.0395933180430763
chisq
39.5933180430763
df
24
pvalue
0.023638187618621
chisq.scaled
39.1136150602653
df.scaled
24
pvalue.scaled
0.0265687152629294
chisq.scaling.factor
1.01226434790218
baseline.chisq
4010.69045035666
baseline.df
36
baseline.pvalue
0
baseline.chisq.scaled
3976.21261425848
baseline.df.scaled
36
baseline.pvalue.scaled
0
baseline.chisq.scaling.factor
1.00867102427434
cfi
0.996076847181476
tli
0.994115270772214
cfi.scaled
0.996164264079158
tli.scaled
0.994246396118737
cfi.robust
0.99615059952433
tli.robust
0.994225899286495
logl
-4261.75022147873
unrestricted.logl
-4241.95356245719
aic
8583.50044295747
bic
8709.93868591013
ntotal
500
bic2
8614.71683163778
scaling.factor.h1
1.00598789331404
scaling.factor.h0
1.00096672964353
rmsea
0.0360477900883863
rmsea.ci.lower
0.0133206537558792
rmsea.ci.upper
0.0554785467010791
rmsea.ci.level
0.9
rmsea.pvalue
0.872609329442447
rmsea.close.h0
0.05
rmsea.notclose.pvalue
2.92071859358351e-05
rmsea.notclose.h0
0.08
rmsea.scaled
0.0354889831030529
rmsea.ci.lower.scaled
0.0124583878620228
rmsea.ci.upper.scaled
0.0548896214404359
rmsea.pvalue.scaled
0.88324809904409
rmsea.notclose.pvalue.scaled
2.18002882029145e-05
rmsea.robust
0.0357059445254148
rmsea.ci.lower.robust
0.0123349424481562
rmsea.ci.upper.robust
0.0553426342690385
rmsea.pvalue.robust
0.876068710519012
rmsea.notclose.pvalue.robust
2.98978644814493e-05
srmr
0.0195584346342506
gfi
0.994230146309336
gfi.ci.lower
0.985281597136529
gfi.ci.upper
0.999811174122434
gfi.ci.level
0.9
gfi.robust
0.994359477575713
gfi.ci.lower.robust
0.985362374926487
gfi.ci.upper.robust
0.999942565997681
$pe
A data.frame: 36 × 11
lhs
op
rhs
label
exo
est
se
z
pvalue
std.lv
std.all
<chr>
<chr>
<chr>
<chr>
<int>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
1
stress
=~
stress1
0
1.000000000
0.00000000
NA
NA
0.743305042
0.868605970
2
stress
=~
stress2
0
0.888712566
0.03942880
22.5396804
0.000000e+00
0.660584531
0.807109561
3
stress
=~
stress3
0
1.165333138
0.04482736
25.9960266
0.000000e+00
0.866197997
0.917815829
4
resilience
=~
resil1
0
1.000000000
0.00000000
NA
NA
0.771457415
0.896166093
5
resilience
=~
resil2
0
0.851920295
0.03803463
22.3985404
0.000000e+00
0.657220229
0.803459938
6
resilience
=~
resil3
0
1.123935553
0.04081111
27.5399390
0.000000e+00
0.867068417
0.905885416
7
depression
=~
dep1
0
1.000000000
0.00000000
NA
NA
1.115486326
0.939423104
8
depression
=~
dep2
0
0.852686146
0.02411456
35.3598025
0.000000e+00
0.951159737
0.891874563
9
depression
=~
dep3
0
1.146769075
0.02812917
40.7679698
0.000000e+00
1.279205223
0.950922084
10
resilience
~
stress
a
0
-0.536162652
0.04762429
-11.2581761
0.000000e+00
-0.516596762
-0.516596762
11
depression
~
resilience
b
0
-0.638717896
0.05328262
-11.9873592
0.000000e+00
-0.441729894
-0.441729894
12
depression
~
stress
c
0
0.727534488
0.05931887
12.2648068
0.000000e+00
0.484793081
0.484793081
13
stress1
~~
stress1
0
0.179796776
0.01502218
11.9687500
0.000000e+00
0.179796776
0.245523668
14
stress2
~~
stress2
0
0.233500062
0.01873282
12.4647549
0.000000e+00
0.233500062
0.348574156
15
stress3
~~
stress3
0
0.140384235
0.01809214
7.7594060
8.437695e-15
0.140384235
0.157614104
16
resil1
~~
resil1
0
0.145902412
0.01518287
9.6096700
0.000000e+00
0.145902412
0.196886334
17
resil2
~~
resil2
0
0.237165208
0.01635885
14.4976666
0.000000e+00
0.237165208
0.354452128
18
resil3
~~
resil3
0
0.164328886
0.02044476
8.0377007
8.881784e-16
0.164328886
0.179371612
19
dep1
~~
dep1
0
0.165647777
0.01833613
9.0339534
0.000000e+00
0.165647777
0.117484232
20
dep2
~~
dep2
0
0.232658848
0.01754117
13.2635869
0.000000e+00
0.232658848
0.204559764
21
dep3
~~
dep3
0
0.173267305
0.02076417
8.3445350
0.000000e+00
0.173267305
0.095747191
22
stress
~~
stress
0
0.552502385
0.04624425
11.9474836
0.000000e+00
1.000000000
1.000000000
23
resilience
~~
resilience
0
0.436318467
0.03737519
11.6740140
0.000000e+00
0.733127786
0.733127786
24
depression
~~
depression
0
0.433759482
0.03861860
11.2318795
0.000000e+00
0.348594459
0.348594459
25
stress1
~1
0
0.051164260
0.03827007
1.3369262
1.812467e-01
0.051164260
0.059789157
26
stress2
~1
0
-0.007807425
0.03660251
-0.2133030
8.310907e-01
-0.007807425
-0.009539199
27
stress3
~1
0
0.040657971
0.04220624
0.9633167
3.353886e-01
0.040657971
0.043080830
28
resil1
~1
0
-0.024374481
0.03849803
-0.6331359
5.266449e-01
-0.024374481
-0.028314698
29
resil2
~1
0
-0.011269369
0.03658152
-0.3080618
7.580353e-01
-0.011269369
-0.013776944
30
resil3
~1
0
-0.035980507
0.04280506
-0.8405667
4.005907e-01
-0.035980507
-0.037591286
31
dep1
~1
0
0.037102437
0.05310288
0.6986898
4.847459e-01
0.037102437
0.031246359
32
dep2
~1
0
0.047620784
0.04769411
0.9984627
3.180551e-01
0.047620784
0.044652611
33
dep3
~1
0
0.069974908
0.06016035
1.1631401
2.447727e-01
0.069974908
0.052017209
37
indirect
:=
a*b
indirect
0
0.342456681
0.04001743
8.5576878
0.000000e+00
0.228196233
0.228196233
38
direct
:=
c
direct
0
0.727534488
0.05931887
12.2648068
0.000000e+00
0.484793081
0.484793081
39
total
:=
c+(a*b)
total
0
1.069991169
0.06527865
16.3911355
0.000000e+00
0.712989314
0.712989314
MLR provides robust (sandwich-type) standard errors and a robust test statistic. In this dataset it changes very little — the raw chi-square is identical (39.593, df = 24), with a Yuan-Bentler scaled chi-square of 39.11 (scaling factor ≈ 1.01) and a robust RMSEA of 0.036 — reassuring, since it suggests the normal-theory results weren’t being distorted by non-normality in the simulated data.
17.4 Missing Data
SEM can handle missing data using full information maximum likelihood (FIML):
This is generally preferable to simply deleting all rows with missing values (listwise deletion), assuming the missing-data mechanism is appropriate for FIML (missing at random).
18 Modification Indices
Modification indices suggest possible model changes that might improve fit.
modindices( fit_sem,sort =TRUE,minimum.value =10)
A lavaan.data.frame: 2 × 8
lhs
op
rhs
mi
epc
sepc.lv
sepc.all
sepc.nox
<chr>
<chr>
<chr>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
66
stress2
~~
stress3
15.32568
-0.08218576
-0.08218576
-0.4539352
-0.4539352
52
depression
=~
stress1
15.31238
-0.13934818
-0.15544099
-0.1816441
-0.1816441
lhs
op
rhs
mi
epc
sepc.all
stress2
stress3
15.33
−0.082
−0.454
depression
=~
stress1
15.31
−0.139
−0.182
Both suggested modifications clear the conventional threshold of 10, but that doesn’t mean either should automatically be added.
Modification indices should be used cautiously. Don’t blindly add paths just because they improve model fit — every added path should have theoretical justification. Otherwise the model becomes data-driven and may not replicate.
19 Reporting SEM Results
A clear SEM report should include: the theoretical model, a description of the observed indicators, the estimator used, the sample size, model fit indices, standardized factor loadings, structural path coefficients, direct/indirect/total effects if mediation is tested, any model modifications, and limitations.
Example reporting paragraph:
We fitted a structural equation model to examine whether resilience mediated the association between stress and depression. Stress, resilience, and depression were modeled as latent variables, each measured by three observed indicators. The model showed acceptable fit according to CFI, TLI, RMSEA, and SRMR. Standardized path estimates indicated that higher stress was associated with lower resilience, and higher resilience was associated with lower depression. The indirect effect from stress to depression through resilience was estimated using bootstrapped confidence intervals.
20 Common Mistakes in SEM
Mistake 1: Treating SEM as causal proof. SEM can represent causal hypotheses, but it does not prove causality by itself. Causal interpretation depends on study design, theory, temporal ordering, confounding control, and the underlying assumptions.
Mistake 2: Ignoring the measurement model. If the latent variables are poorly measured, the structural paths built on top of them may not be meaningful.
Mistake 3: Chasing fit indices. Good fit indices do not guarantee that the model is scientifically meaningful.
Mistake 4: Overfitting with modification indices. Adding many paths based only on modification indices can make the model fit the current dataset while failing to replicate in future ones.
Mistake 5: Reporting only p-values. SEM results should include effect sizes, standardized estimates, confidence intervals, and model fit indices — not p-values alone.
lavaan NOTE:
Standard errors and confidence intervals of the (nonlinear) defined (:=)
parameters are based on the first-order delta method; for strongly
nonlinear definitions, se.def = "mc" (Monte Carlo) or se = "bootstrap" may
be more accurate.
$header
$lavaan.version
'0.7-2'
$sam.approach
FALSE
$optim.method
'nlminb'
$optim.iterations
34
$optim.converged
TRUE
$optim
$estimator
'ML'
$estimator.args
$optim.method
'nlminb'
$npar
30
$eq.constraints
FALSE
$nrow.ceq.jac
0
$nrow.cin.jac
0
$nrow.con.jac
0
$con.jac.rank
0
$data
$ngroups
1
$nobs
500
$test
$standard =
$test
'standard'
$stat
39.5933180430763
$stat.group
39.5933180430763
$df
24
$refdistr
'chisq'
$pvalue
0.023638187618621
$fit
npar
30
fmin
0.0395933180430763
chisq
39.5933180430763
df
24
pvalue
0.023638187618621
baseline.chisq
4010.69045035666
baseline.df
36
baseline.pvalue
0
cfi
0.996076847181476
tli
0.994115270772214
logl
-4261.75022147873
unrestricted.logl
-4241.95356245719
aic
8583.50044295747
bic
8709.93868591013
ntotal
500
bic2
8614.71683163778
rmsea
0.0360477900883863
rmsea.ci.lower
0.0133206537558792
rmsea.ci.upper
0.0554785467010791
rmsea.ci.level
0.9
rmsea.pvalue
0.872609329442447
rmsea.close.h0
0.05
rmsea.notclose.pvalue
2.92071859358351e-05
rmsea.notclose.h0
0.08
srmr
0.0195584346342506
gfi
0.994230146309336
gfi.ci.lower
0.985281597136529
gfi.ci.upper
0.999811174122434
gfi.ci.level
0.9
$pe
A data.frame: 47 × 11
lhs
op
rhs
label
exo
est
se
z
pvalue
std.lv
std.all
<chr>
<chr>
<chr>
<chr>
<int>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
1
stress
=~
stress1
0
1.000000000
0.00000000
NA
NA
0.743305042
0.868605970
2
stress
=~
stress2
0
0.888712566
0.03965218
22.4127048
0.000000e+00
0.660584531
0.807109561
3
stress
=~
stress3
0
1.165333138
0.04332610
26.8967905
0.000000e+00
0.866197997
0.917815829
4
resilience
=~
resil1
0
1.000000000
0.00000000
NA
NA
0.771457415
0.896166093
5
resilience
=~
resil2
0
0.851920295
0.03685346
23.1164239
0.000000e+00
0.657220229
0.803459938
6
resilience
=~
resil3
0
1.123935553
0.04011596
28.0171692
0.000000e+00
0.867068417
0.905885416
7
depression
=~
dep1
0
1.000000000
0.00000000
NA
NA
1.115486326
0.939423104
8
depression
=~
dep2
0
0.852686146
0.02485828
34.3018961
0.000000e+00
0.951159737
0.891874563
9
depression
=~
dep3
0
1.146769075
0.02726355
42.0623568
0.000000e+00
1.279205223
0.950922084
10
resilience
~
stress
a
0
-0.536162652
0.04798759
-11.1729444
0.000000e+00
-0.516596762
-0.516596762
11
depression
~
resilience
b
0
-0.638717896
0.05641726
-11.3213206
0.000000e+00
-0.441729894
-0.441729894
12
depression
~
stress
c
0
0.727534488
0.05968082
12.1904241
0.000000e+00
0.484793081
0.484793081
13
stress1
~~
stress1
0
0.179796776
0.01664951
10.7989246
0.000000e+00
0.179796776
0.245523668
14
stress2
~~
stress2
0
0.233500062
0.01801124
12.9641268
0.000000e+00
0.233500062
0.348574156
15
stress3
~~
stress3
0
0.140384235
0.01830990
7.6671204
1.754152e-14
0.140384235
0.157614104
16
resil1
~~
resil1
0
0.145902412
0.01563347
9.3326929
0.000000e+00
0.145902412
0.196886334
17
resil2
~~
resil2
0
0.237165208
0.01806223
13.1304497
0.000000e+00
0.237165208
0.354452128
18
resil3
~~
resil3
0
0.164328886
0.01895948
8.6673739
0.000000e+00
0.164328886
0.179371612
19
dep1
~~
dep1
0
0.165647777
0.01695952
9.7672442
0.000000e+00
0.165647777
0.117484232
20
dep2
~~
dep2
0
0.232658848
0.01803935
12.8972957
0.000000e+00
0.232658848
0.204559764
21
dep3
~~
dep3
0
0.173267305
0.02052209
8.4429653
0.000000e+00
0.173267305
0.095747191
22
stress
~~
stress
0
0.552502385
0.04651494
11.8779564
0.000000e+00
1.000000000
1.000000000
23
resilience
~~
resilience
0
0.436318467
0.03668041
11.8951349
0.000000e+00
0.733127786
0.733127786
24
depression
~~
depression
0
0.433759482
0.03669715
11.8199764
0.000000e+00
0.348594459
0.348594459
25
stress1
~1
0
0.051164260
0.03827007
1.3369262
1.812467e-01
0.051164260
0.059789157
26
stress2
~1
0
-0.007807425
0.03660251
-0.2133030
8.310907e-01
-0.007807425
-0.009539199
27
stress3
~1
0
0.040657971
0.04220624
0.9633167
3.353886e-01
0.040657971
0.043080830
28
resil1
~1
0
-0.024374481
0.03849802
-0.6331359
5.266449e-01
-0.024374481
-0.028314698
29
resil2
~1
0
-0.011269369
0.03658152
-0.3080618
7.580353e-01
-0.011269369
-0.013776944
30
resil3
~1
0
-0.035980507
0.04280506
-0.8405667
4.005907e-01
-0.035980507
-0.037591286
31
dep1
~1
0
0.037102437
0.05310287
0.6986898
4.847459e-01
0.037102437
0.031246359
32
dep2
~1
0
0.047620784
0.04769410
0.9984627
3.180550e-01
0.047620784
0.044652611
33
dep3
~1
0
0.069974908
0.06016034
1.1631401
2.447726e-01
0.069974908
0.052017209
37
indirect
:=
a*b
indirect
0
0.342456681
0.04061961
8.4308214
0.000000e+00
0.228196233
0.228196233
38
direct
:=
c
direct
0
0.727534488
0.05968082
12.1904241
0.000000e+00
0.484793081
0.484793081
39
total
:=
c+(a*b)
total
0
1.069991169
0.06169700
17.3426763
0.000000e+00
0.712989314
0.712989314
40
stress1
r2
stress1
0
0.754476332
NA
NA
NA
NA
NA
41
stress2
r2
stress2
0
0.651425844
NA
NA
NA
NA
NA
42
stress3
r2
stress3
0
0.842385896
NA
NA
NA
NA
NA
43
resil1
r2
resil1
0
0.803113666
NA
NA
NA
NA
NA
44
resil2
r2
resil2
0
0.645547872
NA
NA
NA
NA
NA
45
resil3
r2
resil3
0
0.820628388
NA
NA
NA
NA
NA
46
dep1
r2
dep1
0
0.882515768
NA
NA
NA
NA
NA
47
dep2
r2
dep2
0
0.795440236
NA
NA
NA
NA
NA
48
dep3
r2
dep3
0
0.904252809
NA
NA
NA
NA
NA
49
resilience
r2
resilience
0
0.266872214
NA
NA
NA
NA
NA
50
depression
r2
depression
0
0.651405541
NA
NA
NA
NA
NA
chisq
39.5933180430763
df
24
pvalue
0.023638187618621
cfi
0.996076847181476
tli
0.994115270772214
rmsea
0.0360477900883863
srmr
0.0195584346342506
A lavaan.data.frame: 39 × 12
lhs
op
rhs
label
est
se
z
pvalue
ci.lower
ci.upper
std.lv
std.all
<chr>
<chr>
<chr>
<chr>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
stress
=~
stress1
1.000000000
0.00000000
NA
NA
1.00000000
1.00000000
0.743305042
0.868605970
stress
=~
stress2
0.888712566
0.03965218
22.4127048
0.000000e+00
0.81099572
0.96642941
0.660584531
0.807109561
stress
=~
stress3
1.165333138
0.04332610
26.8967905
0.000000e+00
1.08041554
1.25025074
0.866197997
0.917815829
resilience
=~
resil1
1.000000000
0.00000000
NA
NA
1.00000000
1.00000000
0.771457415
0.896166093
resilience
=~
resil2
0.851920295
0.03685346
23.1164239
0.000000e+00
0.77968883
0.92415176
0.657220229
0.803459938
resilience
=~
resil3
1.123935553
0.04011596
28.0171692
0.000000e+00
1.04530972
1.20256138
0.867068417
0.905885416
depression
=~
dep1
1.000000000
0.00000000
NA
NA
1.00000000
1.00000000
1.115486326
0.939423104
depression
=~
dep2
0.852686146
0.02485828
34.3018961
0.000000e+00
0.80396481
0.90140748
0.951159737
0.891874563
depression
=~
dep3
1.146769075
0.02726355
42.0623568
0.000000e+00
1.09333350
1.20020465
1.279205223
0.950922084
resilience
~
stress
a
-0.536162652
0.04798759
-11.1729444
0.000000e+00
-0.63021660
-0.44210871
-0.516596762
-0.516596762
depression
~
resilience
b
-0.638717896
0.05641726
-11.3213206
0.000000e+00
-0.74929370
-0.52814210
-0.441729894
-0.441729894
depression
~
stress
c
0.727534488
0.05968082
12.1904241
0.000000e+00
0.61056223
0.84450674
0.484793081
0.484793081
stress1
~~
stress1
0.179796776
0.01664951
10.7989246
0.000000e+00
0.14716434
0.21242921
0.179796776
0.245523668
stress2
~~
stress2
0.233500062
0.01801124
12.9641268
0.000000e+00
0.19819867
0.26880145
0.233500062
0.348574156
stress3
~~
stress3
0.140384235
0.01830990
7.6671204
1.754152e-14
0.10449748
0.17627099
0.140384235
0.157614104
resil1
~~
resil1
0.145902412
0.01563347
9.3326929
0.000000e+00
0.11526137
0.17654346
0.145902412
0.196886334
resil2
~~
resil2
0.237165208
0.01806223
13.1304497
0.000000e+00
0.20176389
0.27256653
0.237165208
0.354452128
resil3
~~
resil3
0.164328886
0.01895948
8.6673739
0.000000e+00
0.12716899
0.20148878
0.164328886
0.179371612
dep1
~~
dep1
0.165647777
0.01695952
9.7672442
0.000000e+00
0.13240773
0.19888783
0.165647777
0.117484232
dep2
~~
dep2
0.232658848
0.01803935
12.8972957
0.000000e+00
0.19730237
0.26801533
0.232658848
0.204559764
dep3
~~
dep3
0.173267305
0.02052209
8.4429653
0.000000e+00
0.13304475
0.21348986
0.173267305
0.095747191
stress
~~
stress
0.552502385
0.04651494
11.8779564
0.000000e+00
0.46133479
0.64366999
1.000000000
1.000000000
resilience
~~
resilience
0.436318467
0.03668041
11.8951349
0.000000e+00
0.36442618
0.50821076
0.733127786
0.733127786
depression
~~
depression
0.433759482
0.03669715
11.8199764
0.000000e+00
0.36183438
0.50568458
0.348594459
0.348594459
stress1
~1
0.051164260
0.03827007
1.3369262
1.812467e-01
-0.02384370
0.12617222
0.051164260
0.059789157
stress2
~1
-0.007807425
0.03660251
-0.2133030
8.310907e-01
-0.07954703
0.06393218
-0.007807425
-0.009539199
stress3
~1
0.040657971
0.04220624
0.9633167
3.353886e-01
-0.04206473
0.12338067
0.040657971
0.043080830
resil1
~1
-0.024374481
0.03849802
-0.6331359
5.266449e-01
-0.09982922
0.05108026
-0.024374481
-0.028314698
resil2
~1
-0.011269369
0.03658152
-0.3080618
7.580353e-01
-0.08296782
0.06042908
-0.011269369
-0.013776944
resil3
~1
-0.035980507
0.04280506
-0.8405667
4.005907e-01
-0.11987688
0.04791587
-0.035980507
-0.037591286
dep1
~1
0.037102437
0.05310287
0.6986898
4.847459e-01
-0.06697728
0.14118215
0.037102437
0.031246359
dep2
~1
0.047620784
0.04769410
0.9984627
3.180550e-01
-0.04585794
0.14109951
0.047620784
0.044652611
dep3
~1
0.069974908
0.06016034
1.1631401
2.447726e-01
-0.04793719
0.18788701
0.069974908
0.052017209
stress
~1
0.000000000
0.00000000
NA
NA
0.00000000
0.00000000
0.000000000
0.000000000
resilience
~1
0.000000000
0.00000000
NA
NA
0.00000000
0.00000000
0.000000000
0.000000000
depression
~1
0.000000000
0.00000000
NA
NA
0.00000000
0.00000000
0.000000000
0.000000000
indirect
:=
a*b
indirect
0.342456681
0.04061961
8.4308214
0.000000e+00
0.26284371
0.42206965
0.228196233
0.228196233
direct
:=
c
direct
0.727534488
0.05968082
12.1904241
0.000000e+00
0.61056223
0.84450674
0.484793081
0.484793081
total
:=
c+(a*b)
total
1.069991169
0.06169700
17.3426763
0.000000e+00
0.94906726
1.19091507
0.712989314
0.712989314
A lavaan.data.frame: 39 × 12
lhs
op
rhs
label
est
se
z
pvalue
ci.lower
ci.upper
std.lv
std.all
<chr>
<chr>
<chr>
<chr>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
<dbl>
stress
=~
stress1
1.000000000
0.00000000
NA
NA
1.00000000
1.00000000
0.743305042
0.868605970
stress
=~
stress2
0.888712566
0.03875278
22.9328715
0.000000e+00
0.81296490
0.96278456
0.660584531
0.807109561
stress
=~
stress3
1.165333138
0.04330515
26.9098040
0.000000e+00
1.08137123
1.25711142
0.866197997
0.917815829
resilience
=~
resil1
1.000000000
0.00000000
NA
NA
1.00000000
1.00000000
0.771457415
0.896166093
resilience
=~
resil2
0.851920295
0.03808626
22.3681820
0.000000e+00
0.77898450
0.92590202
0.657220229
0.803459938
resilience
=~
resil3
1.123935553
0.04317346
26.0330200
0.000000e+00
1.04008005
1.21317797
0.867068417
0.905885416
depression
=~
dep1
1.000000000
0.00000000
NA
NA
1.00000000
1.00000000
1.115486326
0.939423104
depression
=~
dep2
0.852686146
0.02355667
36.1972280
0.000000e+00
0.80457833
0.89658444
0.951159737
0.891874563
depression
=~
dep3
1.146769075
0.02873547
39.9077899
0.000000e+00
1.09159357
1.20370831
1.279205223
0.950922084
resilience
~
stress
a
-0.536162652
0.04772853
-11.2335886
0.000000e+00
-0.63015064
-0.44693992
-0.516596762
-0.516596762
depression
~
resilience
b
-0.638717896
0.05169940
-12.3544541
0.000000e+00
-0.74788338
-0.54120024
-0.441729894
-0.441729894
depression
~
stress
c
0.727534488
0.05869613
12.3949303
0.000000e+00
0.61975331
0.85032347
0.484793081
0.484793081
stress1
~~
stress1
0.179796776
0.01502245
11.9685414
0.000000e+00
0.14883131
0.20843282
0.179796776
0.245523668
stress2
~~
stress2
0.233500062
0.01885213
12.3858737
0.000000e+00
0.19576134
0.27184260
0.233500062
0.348574156
stress3
~~
stress3
0.140384235
0.01843239
7.6161708
2.620126e-14
0.10418247
0.17538170
0.140384235
0.157614104
resil1
~~
resil1
0.145902412
0.01595743
9.1432259
0.000000e+00
0.11363838
0.17838381
0.145902412
0.196886334
resil2
~~
resil2
0.237165208
0.01709337
13.8746937
0.000000e+00
0.20370321
0.27054419
0.237165208
0.354452128
resil3
~~
resil3
0.164328886
0.02084598
7.8830019
3.108624e-15
0.12386293
0.20364139
0.164328886
0.179371612
dep1
~~
dep1
0.165647777
0.01906716
8.6875974
0.000000e+00
0.12656908
0.20048704
0.165647777
0.117484232
dep2
~~
dep2
0.232658848
0.01764236
13.1875122
0.000000e+00
0.19903614
0.26820314
0.232658848
0.204559764
dep3
~~
dep3
0.173267305
0.02048533
8.4581171
0.000000e+00
0.13453217
0.21504703
0.173267305
0.095747191
stress
~~
stress
0.552502385
0.04695879
11.7656873
0.000000e+00
0.46231792
0.64888754
1.000000000
1.000000000
resilience
~~
resilience
0.436318467
0.03765419
11.5875151
0.000000e+00
0.36516158
0.50533324
0.733127786
0.733127786
depression
~~
depression
0.433759482
0.03872977
11.1996388
0.000000e+00
0.35791846
0.51338908
0.348594459
0.348594459
stress1
~1
0.051164260
0.03771417
1.3566322
1.748981e-01
-0.02531084
0.12307179
0.051164260
0.059789157
stress2
~1
-0.007807425
0.03691312
-0.2115081
8.324908e-01
-0.08111150
0.06529539
-0.007807425
-0.009539199
stress3
~1
0.040657971
0.04279942
0.9499654
3.421298e-01
-0.04122633
0.12437364
0.040657971
0.043080830
resil1
~1
-0.024374481
0.03766567
-0.6471272
5.175496e-01
-0.09808678
0.05658945
-0.024374481
-0.028314698
resil2
~1
-0.011269369
0.03674697
-0.3066748
7.590909e-01
-0.08130063
0.06230864
-0.011269369
-0.013776944
resil3
~1
-0.035980507
0.04224272
-0.8517564
3.943493e-01
-0.11875072
0.04734353
-0.035980507
-0.037591286
dep1
~1
0.037102437
0.05255557
0.7059658
4.802094e-01
-0.06456298
0.14260961
0.037102437
0.031246359
dep2
~1
0.047620784
0.04743160
1.0039886
3.153841e-01
-0.04997907
0.14185914
0.047620784
0.044652611
dep3
~1
0.069974908
0.05921142
1.1817807
2.372927e-01
-0.05015772
0.18235691
0.069974908
0.052017209
stress
~1
0.000000000
0.00000000
NA
NA
0.00000000
0.00000000
0.000000000
0.000000000
resilience
~1
0.000000000
0.00000000
NA
NA
0.00000000
0.00000000
0.000000000
0.000000000
depression
~1
0.000000000
0.00000000
NA
NA
0.00000000
0.00000000
0.000000000
0.000000000
indirect
:=
a*b
indirect
0.342456681
0.03929570
8.7148636
0.000000e+00
0.26652179
0.41898946
0.228196233
0.228196233
direct
:=
c
direct
0.727534488
0.05869613
12.3949303
0.000000e+00
0.61975331
0.85032347
0.484793081
0.484793081
total
:=
c+(a*b)
total
1.069991169
0.06601319
16.2087480
0.000000e+00
0.94318488
1.20050726
0.712989314
0.712989314
22 Final Takeaway
Structural Equation Modeling is a powerful method for studying complex relationships among observed and latent variables. It’s especially useful when a research question involves measurement error, latent constructs, mediation, and multiple pathways at once.
A good SEM analysis should not start from software — it should start from theory. The main question is not only:
Which paths are significant?
A better question is:
Does this theoretical model provide a reasonable and interpretable explanation of the observed data?
SEM is strongest when statistical modeling, measurement quality, and domain theory are used together.
23 References
Rosseel, Y. (2012). lavaan: An R Package for Structural Equation Modeling. Journal of Statistical Software, 48(2), 1–36.