Multiple group CFA (or SEM) with different structures?

176 views
Skip to first unread message

Shu Fai Cheung (張樹輝)

unread,
Jul 3, 2023, 11:59:59 PM7/3/23
to lavaan
Hi All,

I vaguely recall I have read somewhere, maybe here, that we can fit different models in multiple group CFA or SEM, with the models having variables not shared across gorups. However, I tried and failed to locate that post, if there is one.

Not just constraining some parameters to zero. The two groups have different variables. Something like this:

HS.model <-
"
# Group1:
factor1  =~ x1 + x2 + x3
factor2  =~ x7 + x8 + x9
# Group2:
factor1  =~ x1 + x2 + x3
factor3  =~ x4 + x5 + x6
"

Note that this is not a missing data problem because x4 to x6 were not measured in Group1 for some reasons. x4 to x6 may even be not applicable to Group1 and so could *not* be meaningfully responded to even if they were administered to Group1. E.g., Group1 is working adults but x4 to x6 are about school life. Similarly, x7 to x8 were not measured in Group2.

Is it possible in lavaan? If yes, how to fit this model? It may be something related to "blocks" but I have never used this feature.

-- Shu Fai

Jasper Bogaert

unread,
Jul 4, 2023, 4:34:11 AM7/4/23
to lavaan
Hi Shu Fai,

I am not sure whether this is what you need, but I found this: 
Best wishes,

Jasper
Op dinsdag 4 juli 2023 om 05:59:59 UTC+2 schreef shufai...@gmail.com:

Shu Fai Cheung (張樹輝)

unread,
Jul 4, 2023, 4:54:00 AM7/4/23
to lavaan
Dear Jasper,

Many many thanks! My bad memory! This is exactly what I want (and what I have read, I believe, though I have zero memory of them).

By the way, this is an interesting technique, though I don't know where it is covered in the documentation.

-- Shu Fai

Jasper Bogaert

unread,
Jul 5, 2023, 3:00:12 AM7/5/23
to lavaan
Dear Shu Fai,

You are welcome!  Unfortunately, I believe it is (currently) not included in the documentation (or at least I was not able to find it).

Best wishes,

Jasper
Op dinsdag 4 juli 2023 om 10:54:00 UTC+2 schreef shufai...@gmail.com:

Christian Arnold

unread,
Jul 5, 2023, 8:05:22 AM7/5/23
to lavaan
A few more thoughts. One can write a very clear and easy to read syntax even if parameter labels are involved.

HS.model <- "
group: Pasteur
visual  =~ x1 + a1 * x2 + x3
textual =~ x4 + x5 + x6
speed   =~ x7 + x8 + x9

group: Grant-White
visual  =~ x1 + a2 * x2 + x3
textual =~ x4 + x5 + x6
speed   =~ x7

param := a2 - a1
"

fit <- cfa(HS.model, HolzingerSwineford1939, group = "school")
parameterEstimates(fit)


I think this notation makes a lot of sense! Thanks for the implementation!

However, I noticed that this solution does not work (the group assignment is wrong):

HS.model <- "
group: Grant-White
visual  =~ x1 + a1 * x2 + x3
textual =~ x4 + x5 + x6
speed   =~ x7 + x8 + x9

group: Pasteur
visual  =~ x1 + a2 * x2 + x3
textual =~ x4 + x5 + x6
speed   =~ x7

param := a2 - a1
"
fit <- cfa(HS.model, HolzingerSwineford1939, group = "school")


One can correct it as follows:

fit <- cfa(HS.model, HolzingerSwineford1939, group = "school", group.label = c("Grant-White", "Pasteur"))

However, I wonder if it is really necessary to pass the "group" and "group.label" arguments. After all, this is already specified as part of the model syntax and is ultimately a redundancy. Could this be changed?

Terrence Jorgensen

unread,
Jul 21, 2023, 9:57:06 AM7/21/23
to lavaan
I wonder if it is really necessary to pass the "group" and "group.label" arguments. After all, this is already specified as part of the model syntax and is ultimately a redundancy. Could this be changed?

The parser for "blocks" of syntax is not currently very "smart", but it is highly flexible.  All it does is create a new section column/index in the parameter table.  The numbers or labels you assign to a block are completely arbitrary, and are not "matched" against the data in any way.  For instance, I can give groups arbitrary labels "buttery" and "salty".

HS.model <- "
group: buttery

visual  =~ x1 + a1 * x2 + x3
textual =~ x4 + x5 + x6
speed   =~ x7 + x8 + x9

group: salty

visual  =~ x1 + a2 * x2 + x3
textual =~ x4 + x5 + x6
speed   =~ x7

param := a2 - a1
"
lavaanify(HS.model, ngroups=2)
fit <- cfa(HS.model, HolzingerSwineford1939, group = "school")
summary(fit)
parTable(fit)

Notice the labels in the summary() are still the levels of school, but the flavor labels are still preserved in the parameter table.  The first label you provide simply corresponds to the first level of the grouping variable. So the group.label= argument is needed to set a different order.

Another thing to note carefully is not to bounce back and forth between blocks, although it might not seem to be important.

HS.model <- "
group: Grant-White
visual  =~ x1 + x2 + x3

group: Pasteur
visual  =~ x1 + x2 + x3

group: Grant-White

textual =~ x4 + x5 + x6

group: Pasteur

textual =~ x4 + x5 + x6
"

This does not simply assign parameters (one set at a time) to 2 groups.  When the parser sees group: Grant-White a second time, it assigns a new (third) block in the parameter table, which leads to an error because there are only 2 groups.

I wouldn't expect lavaan's parser to get "smarter" about that.  The need for flexibility of this feature outweighs the desire for easy specification.  And this block structure is only necessary in situations when specification should be tedious and deliberate, not reliant on assumed defaults.

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

Christian Arnold

unread,
Jul 21, 2023, 2:31:41 PM7/21/23
to lav...@googlegroups.com
Hi Terrence,

Thanks for your assessment. It may be a tradeoff, but redundancy is not unpopular in IT withoiut a reason. One could certainly add a lot of usability here.

Best

Christian 

From: lav...@googlegroups.com <lav...@googlegroups.com> on behalf of Terrence Jorgensen <tjorge...@gmail.com>
Sent: Friday, July 21, 2023 3:57:06 PM
To: lavaan <lav...@googlegroups.com>
Subject: Re: Multiple group CFA (or SEM) with different structures?
 
--
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/8b654f23-7975-41b7-8239-9c2643fbf726n%40googlegroups.com.

Terrence Jorgensen

unread,
Jul 22, 2023, 3:08:18 AM7/22/23
to lavaan
It should probably also be mentioned that this is not documented because it is not an intended feature for MG modeling. The feature is intended for ML-SEMs, which can (and often do) have different variables across levels (e.g., level-2 covariates).  The fact that block structured syntax can also be defined for groups is an interesting and useful hack, and one that is currently necessary for multigroup+multilevel SEMs because the parser isn’t yet designed to detect groups within each level’s model (I suspect part of that difficulty is that levels must be nested in top-level groups, not the other way around). 

Christian Arnold

unread,
Jul 22, 2023, 3:50:48 PM7/22/23
to lav...@googlegroups.com
Well, it's there and it's good, right? Innovations don't always have to be intentional. There are great opportunities here. I like the feature, even though your points are worth considering. It is a great functionality. Especially for researchers who switch from Amos to lavaan.

Best

Christian 

From: lav...@googlegroups.com <lav...@googlegroups.com> on behalf of Terrence Jorgensen <tjorge...@gmail.com>
Sent: Saturday, July 22, 2023 9:08:18 AM

To: lavaan <lav...@googlegroups.com>
Subject: Re: Multiple group CFA (or SEM) with different structures?
--
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.
Reply all
Reply to author
Forward
0 new messages