The overt intent of this example is to illustrate the use of blavaan for studying measurement invariance. Along the way, we will also see how to obtain Bayesian model selection measures and how to send a lavaan object directly to blavaan for re-estimation.
Model Estimation
Consider a measurement invariance study of the Holzinger and Swineford (1939) data. In lavaan, we may first estimate two models:
HS.model <- ' visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9 '
fit1 <- cfa(HS.model, data = HolzingerSwineford1939, group = "school")
fit2 <- cfa(HS.model, data = HolzingerSwineford1939, group = "school",
group.equal = "loadings")
and then examine the absolute fit of fit1
. We could also
compare fit2
to fit1
via a Likelihood Ratio
Test. Instead of this, we wish to do something similar via Bayesian
methods.
To accomplish this via blavaan, we can fit Bayesian versions of
fit1
and fit2
using similar syntax.
bfit1 <- bcfa(HS.model, data = HolzingerSwineford1939, group = "school")
bfit2 <- bcfa(HS.model, data = HolzingerSwineford1939, group = "school",
group.equal = "loadings")
Model fit and comparison statistics are then available via the
fitMeasures()
and blavCompare()
functions:
fitMeasures(bfit1)
fitMeasures(bfit2)
blavCompare(bfit1, bfit2)
Approximate Invariance
In approximate measurement invariance studies, we replace
the hard equality constraints with soft constraints by using informative
prior distributions. The wiggle
argument can be used to
invoke these types of constraints. For example:
HS.model <- ' visual =~ x1 + c("a", "a")*x2 + c("b", "b")*x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9 '
bfit3 <- bcfa(HS.model, data = HolzingerSwineford1939, group = "school", wiggle = c("a", "b"),
wiggle.sd = 0.05)
This constrains the loadings associated with x2
and
x3
to be approximately equal across groups, where the
informative priors associated with these constraints are normal with
standard deviations of 0.05.
Using the above strategy, the syntax can become very cumbersome. In
many cases, the group.equal
argument can help here. For
example:
HS.model <- ' visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9 '
bfit4 <- bcfa(HS.model, data = HolzingerSwineford1939, group = "school",
group.equal = c("intercepts", "loadings"), wiggle = "loadings",
wiggle.sd = 0.05)
In the above example, the model intercepts and loadings have
across-group constraints. The loadings are approximately equal across
groups, due to the argument wiggle = "loadings"
. And the
intercepts are constrained to be exactly equal across groups. In this
way, it becomes easy to use exact and approximate equality constraints
in the same model, if desired.