Set-ESEM with multiple target rotation matrices.

227 views
Skip to first unread message

Hans Chung

unread,
Mar 26, 2026, 7:56:02 AMMar 26
to lavaan
Hi I am seeking to do a Set-ESEM as described by Marsh & Alamar (2024) using lavaan in order to replicate Fan et. al.'s (2023) implementation using MPLUS (see Supplemental A) to compare self report vs machine-predicted personality scores

The model has 2 sets and will implement target rotation on each set to constrain the factor loadings based on a priori knowledge that primary facets should not load on secondary factors.

Is this the correct syntax to ensure both sets are rotated based on the target matrice?
fit <- sem(model = model,  data = data, estimator = "MLR",
                   rotation = "target", 
                    rotation.args = list(target = list(target, target)))

Target and model setup below:
target <- matrix(0, nrow = 30, ncol = 5)
target[1:6, 1] <- NA    # O facets
target[7:12, 2] <- NA   # C facets  
target[13:18, 3] <- NA  # E facets
target[19:24, 4] <- NA  # A facets
target[25:30, 5] <- NA  # N facets

model <- '
efa("SlfRprt")*O +
efa("SlfRprt")*C +
efa("SlfRprt")*E +
efa("SlfRprt")*A +
efa("SlfRprt")*N  =~ O1_sr + O2_sr + ... ... N2_sr + ...

efa("Mchn")*O +
efa("Mchn")*C +
efa("Mchn")*E +
efa("Mchn")*A +
efa("Mchn")*N  =~ O1_m + O2_m + ... ... N2_m + ...

O1_sr ~~ O1_m
... ...
'


Hans Chung

unread,
Apr 1, 2026, 3:13:00 AMApr 1
to lavaan
I have further tested if the target rotation matrices are being applied by reversing the sets in the model (Mchn first then SlfRprt) to see if the results are the same. They differed so i suspect only the first matrice is being applied as Marsh & Alamar described.

I did note that in version 0.6-18EFA: target argument in rotation.args can now be a list with separate matrices per group. So I'm not sure if this refers to something else or if my rotation.args syntax is wrong?

Appreciate if anyone has insight to this thank you!

Michal Kohút

unread,
Apr 2, 2026, 11:44:10 AMApr 2
to lavaan
Hello! I have a similar issue. I tried using two matrices, but only the first one is applied to both sets in set-ESEM. It works in my case because both sets and therefore the matrices are identical. However, when I tried another model with a different number of items, it returned an error:  nrow(target) != nrow(A). I tried different solutions, but nothing worked for me.  

Dátum: streda 1. apríla 2026, čas: 9:13:00 UTC+2, odosielateľ: hanschu...@gmail.com

Yves Rosseel

unread,
Apr 3, 2026, 11:01:18 AMApr 3
to lav...@googlegroups.com
I am afraid this is currently not possible. There can only be a single
target matrix for all sets (for now). I will have to think about how to
handle this.

Could you open an issue about this on github, so we do not forget?

https://github.com/yrosseel/lavaan/issues

Yves.


On 3/26/26 12:46, Hans Chung wrote:
> Hi I am seeking to do a Set-ESEM as described by Marsh & Alamar (2024)
> <https://bpspsychub.onlinelibrary.wiley.com/doi/10.1111/
> bmsp.12336> using lavaan in order to replicate Fan et. al.'s (2023)
> <https://supp.apa.org/psycarticles/supplemental/apl0001082/
> apl0001082_supp.html> implementation using MPLUS (see Supplemental A) to
> compare self report vs machine-predicted personality scores
>
> The model has 2 sets and will implement target rotation on each set to
> constrain the factor loadings based on a priori knowledge that primary
> facets should not load on secondary factors.
> *
> *
> *Is this the correct syntax to ensure both sets are rotated based on the
> target matrice?*
> fit <- sem(model = model,  data = data, estimator = "MLR",
>                    rotation = "target",
>                     rotation.args = list(target = list(target, target)))
>
> *Target and model setup below:*
> target <- matrix(0, nrow = 30, ncol = 5)
> target[1:6, 1] <- NA    # O facets
> target[7:12, 2] <- NA   # C facets
> target[13:18, 3] <- NA  # E facets
> target[19:24, 4] <- NA  # A facets
> target[25:30, 5] <- NA  # N facets
>
> model <- '
> efa("SlfRprt")*O +
> efa("SlfRprt")*C +
> efa("SlfRprt")*E +
> efa("SlfRprt")*A +
> efa("SlfRprt")*N  =~ O1_sr + O2_sr + ... ... N2_sr + ...
>
> efa("Mchn")*O +
> efa("Mchn")*C +
> efa("Mchn")*E +
> efa("Mchn")*A +
> efa("Mchn")*N  =~ O1_m + O2_m + ... ... N2_m + ...
>
> O1_sr ~~ O1_m
> ... ...
> '
>
>
> --
> 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
> <mailto:lavaan+un...@googlegroups.com>.
> To view this discussion visit https://groups.google.com/d/msgid/
> lavaan/1184e3ce-2b15-42a3-af95-c3b6bd220528n%40googlegroups.com
> <https://groups.google.com/d/msgid/lavaan/1184e3ce-2b15-42a3-af95-
> c3b6bd220528n%40googlegroups.com?utm_medium=email&utm_source=footer>.

Hans Chung

unread,
Apr 6, 2026, 5:17:52 AMApr 6
to lavaan
Hi Yves,

I saw that you mentioned "There can only be a single target matrix for all sets"

Given my target matrix is identical for both sets, I think this would work. But when I compared the factor loadings for model_a and model_b where I swapped the sets, the loadings were different. Not sure what I'm doing wrong or if the target only applies to the first set?


target <- matrix(0, nrow = 30, ncol = 5)
target[1:6, 1] <- NA    # O facets
target[7:12, 2] <- NA   # C facets  
target[13:18, 3] <- NA  # E facets
target[19:24, 4] <- NA  # A facets
target[25:30, 5] <- NA  # N facets

fit <- sem(model = model_a,  data = data, estimator = "MLR",
                   rotation = "target", 
                    rotation.args = list(target = target))

model_a <- '
efa("SlfRprt")*O +
...
efa("SlfRprt")*N  =~ O1_sr + O2_sr + ... ... N2_sr + ...

efa("Mchn")*O +
...
efa("Mchn")*N  =~ O1_m + O2_m + ... ... N2_m + ...

O1_sr ~~ O1_m
... ...
'
model_b <- '
efa("Mchn")*O +
...
efa("Mchn")*N  =~ O1_sr + O2_sr + ... ... N2_sr + ...

efa("SlfRprt")*O +
...
efa("SlfRprt")*N  =~ O1_m + O2_m + ... ... N2_m + ...

O1_m ~~ O1_sr
... ...
'

Michal Kohút

unread,
Apr 6, 2026, 6:59:35 AMApr 6
to lavaan
Hi,
Really good point. I tried it as well, and there is also a difference in all standardized loadings. The difference is extremely small—there’s basically no difference within the first six decimal places; the mean absolute difference is only 0.000000168. I didn’t even notice it when working with three decimal places. The question is, what does this mean?

Dátum: pondelok 6. apríla 2026, čas: 11:17:52 UTC+2, odosielateľ: hanschu...@gmail.com

Hans Chung

unread,
Apr 6, 2026, 2:02:20 PMApr 6
to lavaan
I am wondering the same!

Terrence Jorgensen

unread,
Apr 8, 2026, 6:06:21 AMApr 8
to lavaan
There can only be a single target matrix for all sets (for now). I will have to think about how to
handle this.

Could you open an issue about this on github, so we do not forget?

I posted a new issue with a suggestion:


Terrence D. Jorgensen    (he, him, his)
Assistant Professor, Methods and Statistics
Research Institute for Child Development and Education, the University of Amsterdam
http://www.uva.nl/profile/t.d.jorgensen
 

Michal Kohút

unread,
Jul 9, 2026, 4:24:21 AM (13 days ago) Jul 9
to lavaan
Hi, 
I'd like to ask whether there has been any update on this issue.
Dátum: streda 8. apríla 2026, čas: 12:06:21 UTC+2, odosielateľ: Terrence Jorgensen

Yves Rosseel

unread,
Jul 9, 2026, 12:33:22 PM (12 days ago) Jul 9
to lav...@googlegroups.com
working on it ...

On 7/9/26 10:24, Michal Kohút wrote:
> Hi,
> I'd like to ask whether there has been any update on this issue.
> Dátum: streda 8. apríla 2026, čas: 12:06:21 UTC+2, odosielateľ: Terrence
> Jorgensen
>
> There can only be a single target matrix for all sets (for now).
> I will have to think about how to
> handle this.
>
> Could you open an issue about this on github, so we do not forget?
>
>
> I posted a new issue with a suggestion:
>
> https://github.com/yrosseel/lavaan/issues/522 <https://github.com/
> yrosseel/lavaan/issues/522>
>
> Terrence D. Jorgensen    (he, him, his)
> Assistant Professor, Methods and Statistics
> Research Institute for Child Development and Education, the
> University of Amsterdam
> http://www.uva.nl/profile/t.d.jorgensen <http://www.uva.nl/profile/
> t.d.jorgensen>
>
> --
> 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
> <mailto:lavaan+un...@googlegroups.com>.
> To view this discussion visit https://groups.google.com/d/msgid/lavaan/
> f2c2bc68-164e-4f42-aa2b-656a691c9d9cn%40googlegroups.com <https://
> groups.google.com/d/msgid/lavaan/f2c2bc68-164e-4f42-
> aa2b-656a691c9d9cn%40googlegroups.com?utm_medium=email&utm_source=footer>.

--
Yves Rosseel
Department of Data Analysis, Ghent University

Yves Rosseel

unread,
Jul 9, 2026, 3:08:40 PM (12 days ago) Jul 9
to lav...@googlegroups.com
Should work now with the github version. For example:


fit <- sem(model, data = data, rotation = "target",
rotation.args = list(target = list(a = target.a, b =
target.b)))

for a model containing efa("a")*... and efa("b")*... blocks.

Let me know if you experience any problems.

Yves.

Michal Kohút

unread,
Jul 10, 2026, 5:50:58 AM (12 days ago) Jul 10
to lavaan
Hi,

Thank you very much!

I have tried it with an actual (real) model and then tried changing the "a" matrix, followed by the "b" matrix. The results showed that the differences in the standardized loadings were substantial for the changed matrix set, while they were really small (< 10^-6) for the unchanged matrix set, which is probably just due to the "magic" behind the math (optimization? I don't really know, to be honest).

More importantly, when I did not supply the "b" matrix, the model did not run and returned an error - which did not happen before. Also, changing the "b" matrix in the third model now resulted in the expected changes, whereas previously it did not seem to do anything notable.

You can check the script and the standardized loadings here:
https://sts.skrn.sk/setesem/

Please let me know if my thought process makes sense or if I am missing something important in my testing.

Dátum: štvrtok 9. júla 2026, čas: 21:08:40 UTC+2, odosielateľ: yros...@gmail.com

Yves Rosseel

unread,
Jul 10, 2026, 12:35:00 PM (11 days ago) Jul 10
to lav...@googlegroups.com
Hello Michal,

On 7/10/26 11:50, Michal Kohút wrote:
> I have tried it with an actual (real) model and then tried changing the
> "a" matrix, followed by the "b" matrix. The results showed that the
> differences in the standardized loadings were substantial for the
> changed matrix set, while they were really small (< 10^-6) for the
> unchanged matrix set, which is probably just due to the "magic" behind
> the math (optimization? I don't really know, to be honest).

This is to be expected. Rotation of each efa block is an independent
optimization; changing block a's target cannot affect block b's
solution. (The 10^-6 should be zero, but this is convergence noise from
the rotation algorithm.

> More importantly, when I did not supply the "b" matrix, the model did
> not run and returned an error - which did not happen before.

Yes, but that is by design. If you have two efa blocks ("a" and "b"),
and you only provide the "a" target matrix, but not the "b" target
matrix, an error message is given.

Previously, there was only one target matrix, so it ran.

> changing the "b" matrix in the third model now resulted in the expected
> changes, whereas previously it did not seem to do anything notable.

Yup, that's the new feature working.
Reply all
Reply to author
Forward
0 new messages