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",
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.