# Measurement Invariance

`invariance.Rmd`

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.