Measurement Invariance Testing - how to free a parameter only in one group?

574 views
Skip to first unread message

Mónika Koós

unread,
Nov 22, 2022, 11:59:01 AM11/22/22
to lavaan
Dear All,

I ran into a problem when I wanted to conducts partial measurement invariance testing on my model. Based on modification indices, I want to free a specific parameter only in one group - not in all of them. If I were to use group.partial, it would free that parameter in every group. 

fit <- cfa(model, data = ISS , std.lv = TRUE, estimator = "DWLS",
                          group = "gender", group.equal = c("loadings", "intercepts"),
                          group.partial = c("Exh3 ~~Exh3"))

I was also thinking of using the lavTestScore() function, and releasing this exact parameter (with the help of the parTable I could find it) but it won't calculate fit indices of the new model for me (or will it?).

I knwo how to do this in Mplus, the problem is that I have so many groups, and such a large dataset, it is very slow and just not comfortable enough after R. 

I would appriciate so much any help in this topic, thank you in advance!

Edward Rigdon

unread,
Nov 22, 2022, 12:10:25 PM11/22/22
to lav...@googlegroups.com
For that particular parameter, you could use labels in your syntax to specify equality across groups, e.g.,

Exh3 ~~c(NA,b,b,b,b...)*Exh3

would constrain the parameter to equality across all groups except the first. I don't believe that the group.partial would override the equality imposed through using the same label across groups.

--
You received this message because you are subscribed to the Google Groups "lavaan" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lavaan+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lavaan/1d7c1121-0574-44a7-bec9-896036c891a8n%40googlegroups.com.

Mónika Koós

unread,
Nov 29, 2022, 12:52:39 PM11/29/22
to lavaan

Can I have a follow up, practical question about this - on where and how to interject it into the script? (Because I am a beginner to R)

I tried this one, but does not seem to work in this form:

it <- cfa(model, data = ISS , std.lv = TRUE, estimator = "DWLS",
                          group = "gender", group.equal = c("loadings", "intercepts", 
                                                                                        Exh3 ~~c(NA,b,b,b,b)*Exh3))

And another follow up question (which is probably trivial, just not to me): the b-s in your siggestion represent something, or is this just a sign to be equal (as in mplus, where the same label, usually a letter means that we fix something equal).

Thank you so much in advance, I am very greatful for Your help!

Christian Arnold

unread,
Nov 29, 2022, 1:11:24 PM11/29/22
to lav...@googlegroups.com
Hi,

this can't work:


fit <- cfa(model, data = ISS , std.lv = TRUE, estimator = "DWLS",
                          group = "gender", group.equal = c("loadings", "intercepts"Exh3 ~~c(NA,b,b,b,b)*Exh3))

Exh3 ~~c ... must be passed via group.equal. Try something like this:

fit <- cfa(model, data = ISS , std.lv = TRUE, estimator = "DWLS",
                          group = "gender", group.equal = c("loadings", "intercepts"), group.partial = c("Exh3 ~~c(NA,b,b,b,b)*Exh3"))

I don't know if the code above works. I have never done it that way. This might be a bit clearer (but it may also be a matter of taste):

model <- '
... # Your code
Exh3 ~~ c(b0, b1, b1, b1, b1) * Exh3
'

fit <- cfa(model, data = ISS, std.lv = TRUE, estimator = "DWLS", group = "gender", group.equal = c("loadings", "intercepts"))






Von: lav...@googlegroups.com <lav...@googlegroups.com> im Auftrag von Mónika Koós <koos...@gmail.com>
Gesendet: Dienstag, 29. November 2022 18:52
An: lavaan <lav...@googlegroups.com>
Betreff: Re: Measurement Invariance Testing - how to free a parameter only in one group?
 

Edward Rigdon

unread,
Nov 29, 2022, 2:45:20 PM11/29/22
to lav...@googlegroups.com
Monica--
The syntax line:
Exh3 ~~c(NA,b,b,b,b)*Exh3
appears in your model syntax, not in the call to the cfa() function--amid all of your other syntax specifying what model you are trying to estimate. Specific location within the model syntax does not matter, as the lavaan parser will figure it all out.




Terrence Jorgensen

unread,
Dec 1, 2022, 9:13:24 AM12/1/22
to lavaan
There are strange features here.  You specify group = "gender", but your parameter vector has 5 elements.  I understand that gender is not truly binary (nor is biological sex, nor is it even unidimensional), but are you sure there are 5 groups in your sample data?

table(ISS$gender)

Regardless, you cannot combine labels and numerical values in a single vector.  So you would have to specify the parameter twice (on the same line) to use both operations.  Assuming the variance is already a free parameter, freeing it would be redundant; it would suffice to simply give it a different label:

Exh3 ~~ c(different.label, b, b, b, b)*Exh3
# equivalent result: 
# Exh3 ~~ c(b.1, b, b, b, b)*Exh3 + c(NA, NA, NA, NA, NA)*Exh3 

However, you are using DWLS, without specifying any variables as ordered=, so it is unclear whether Exh3 is ordinal.  Because you haven't provided your model syntax, it is not even clear whether Exh3 is an indicator or common factor.  If it is an ordinal, you can't free its (residual) variance because you have not set parameterization = "theta".  If you do so, then the syntax allowing 4 of 5 groups to have different residual variances would be contingent upon one of those groups having a fixed residual variance for identification.  So perhaps something like this:

Exh3 ~~ c(b.1, b, b, b, b)*Exh3 + c(1, NA, NA, NA, NA)*Exh3 

But it all depends on what you are trying to do, which would be much clearer with a replicable syntax example and more thorough description.

Terrence D. Jorgensen
Assistant Professor, Methods and Statistics
Research Institute for Child Development and Education, the University of Amsterdam

Hana Zickgraf

unread,
Jan 8, 2024, 1:29:21 PM1/8/24
to lavaan
Hello,
I'm having a similar problem with attempting to free an intercept in a single group to test partial scalar invariance. Data are imported from SPSS using Haven. There are 5 groups, and I want to free the intercept of var4 in group 1. Here's my syntax, which produces the same result as group.partial (c("var4~1")

cfa.scalar1 <- cfa(mod1, data = serviceMI, estimator = "WLSMV", group = "group",
                  group.equal = c("loadings","intercepts"),
                  group.partial = c("var4*(NA,b,b,b,b) ~1"))

Thank you for your help on this!

Terrence Jorgensen

unread,
Jan 11, 2024, 8:05:01 AM1/11/24
to lavaan
The group.partial= argument is all or nothing.  You don't provide labels/values there, only the parameter name (e.g., "var4~1").  
Labels/values go on the righthand side of the operator:

var4 ~ (b1,b,b,b,b)*1 # different label for group 1
var4 ~ (NA,0,0,0,0)*1 # free only in group 1

To free value for a categorical indicator (some of whose values are fixed for identification), you need to provide a different label and a missing (rather than fixed) value, on the same line of your model syntax.

var4 ~ (b1,b,b,b,b)*1   +   (NA,0,0,0,0)*1

Hana Zickgraf

unread,
Jan 11, 2024, 12:46:32 PM1/11/24
to lavaan
Thank you for the reply! When I run the below syntax I get this error:
Warning message: In names(out)[1L] <- NAME : number of items to replace is not a multiple of replacement length

And group.partial is ignored, intercepts remain fixed across all groups including group 1. 

mod1a <- 'factor=~ var_1+ var_2 + var_3 + (var_4~c(b1,b,b,b,b)*1+c(NA,0,0,0,0)*1) + var_5..00  '

cfa.scalar2 <- cfa(mod1a, data = serviceMI, estimator = "WLSMV", group = "serviceline_r",
                   group.equal = c("loadings", "intercepts"))
                   group.partial = c("var_4~1")

From the lavaan model syntax documentation is pretty clear on how to constrain parameters to equality in model syntax, but I'm confused about how specify groups within model syntax. 
Thanks for your help!
Hana

Terrence Jorgensen

unread,
Jan 14, 2024, 9:11:00 AM1/14/24
to lavaan
mod1a <- 'factor=~ var_1+ var_2 + var_3 + (var_4~c(b1,b,b,b,b)*1+c(NA,0,0,0,0)*1) + var_5..00  '

It looks like you are trying to specify intercepts on the same line as specifying factor loadings.  That will not work.


From the lavaan model syntax documentation is pretty clear on how to constrain parameters to equality in model syntax, but I'm confused about how specify groups within model syntax. 

See the tutorial page for more information:  https://lavaan.ugent.be/tutorial/groups.html

mod1a <- '
## these are factor loadings:
factor=~ var_1+ var_2 + var_3 + var_4

## these are intercepts
var_4 ~ c(b1,b,b,b,b)*1 + c(NA,0,0,0,0)*1
'

Try using the semTools function measEq.syntax(), which I designed to help people write the correct lavaan syntax for models like this.
Reply all
Reply to author
Forward
0 new messages