-
Notifications
You must be signed in to change notification settings - Fork 23
/
invariance.Rmd
78 lines (54 loc) · 3.12 KB
/
invariance.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
---
title: "Measurement Invariance"
bibliography:
- refs.bib
---
```{r echo=FALSE, message=FALSE}
library(blavaan, quietly=TRUE)
library(lavaan, quietly=TRUE)
```
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 @holswi39 data. In lavaan, we may first estimate two models:
```{r, eval=FALSE}
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.
```{r bf1, eval=FALSE}
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:
```{r eval=FALSE}
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:
```{r, eval=FALSE}
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:
```{r, eval=FALSE}
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.
### References