Parameter labeling to estimate indirect effects in a multigroup path model where some parameters are not estimated in one group

107 views
Skip to first unread message

Ryan Castillo

unread,
Jan 7, 2022, 11:13:55 PM1/7/22
to lavaan

Hello (long post, question at bottom),

I am attempting to estimate indirect effects for a multigroup structural model where some paths are estimated in one group but not the other. Before attempting to estimate the indirect effects, I handled situations where a parameter was estimated in one group but not the other by labeling that parameter 'NA' for the first group and '0' for the second. In situations where the parameter was constrained to equality across groups, I used the same label over groups, e.g., (p1, p1). In situations where the parameter was freely estimated across groups, I simply did not add group labels for that parameter. For example:

 Capture1.JPG

Because I am now interested in estimating indirect effects, parameters previously estimated in one group but not the other now require a label instead of 'NA' so I can define the indirect effect in the script. E.g., a parameter previously labeled (NA, 0) is now labeled (p5, 0). For example (see line 19): 

Capture2.JPG

The issue appears to be that, because I have added a parameter label instead of 'NA' in cases where the path is estimated in one group but not the other, lavaan is overriding the '0' for the second group in favor of the parameter label for the first group and is now estimating that parameter for both groups. For example, see line 23 in the output below (p5, group 2, which should be 0):

Capture3.JPG

Because lavaan is estimating parameters where it should not be, the results are now different when I am attempting to estimate the indirect effects. So, my question is relatively simple, but I am new to this group and am trying to provide sufficient information so that someone who knows can help. My question is: when estimating indirect effects, how can I label parameters estimated in one group but not the other such that lavaan does not override the '0' specified for the latter group?

Any insight would be soooooo appreciated. 

Shu Fai Cheung

unread,
Jan 8, 2022, 1:19:45 PM1/8/22
to lavaan
Which version of lavaan did you use? In the version I used (0.6-9), a warning will appear if a parameter has labels in some groups but fixed values in the others.

The following example uses c(NA. 0):

options(width = 132) library(dplyr) #> #> Attaching package: 'dplyr' #> The following objects are masked from 'package:stats': #> #> filter, lag #> The following objects are masked from 'package:base': #> #> intersect, setdiff, setequal, union library(lavaan) #> This is lavaan 0.6-9 #> lavaan is FREE software! Please report any bugs. dat <- HolzingerSwineford1939 mod1 <- " x2 ~ x1 x3 ~ c(NA, 0)*x2 " fit1 <- sem(model = mod1, data = dat, group = "school") filter(parameterEstimates(fit1), lhs == "x3", op == "~") #> lhs op rhs block group est se z pvalue ci.lower ci.upper #> 1 x3 ~ x2 1 1 0.317 0.071 4.443 0 0.177 0.457 #> 2 x3 ~ x2 2 2 0.000 0.000 NA NA 0.000 0.000
The path coefficient is free in Group 1 but fixed to 0 in Group 2, as expected.

The following uses c(b1, 0):
mod2 <- " x2 ~ x1 x3 ~ c(b1, 0)*x2 " fit2 <- sem(model = mod2, data = dat, group = "school") #> Warning in lavaanify(model = FLAT, constraints = constraints, varTable = lavdata@ov, : lavaan WARNING: using a single label per parameter in a multiple group #> setting implies imposing equality constraints across all the groups; #> If this is not intended, either remove the label(s), or use a vector #> of labels (one for each group); #> See the Multiple groups section in the man page of model.syntax. filter(parameterEstimates(fit2), lhs == "x3", op == "~") #> lhs op rhs block group label est se z pvalue ci.lower ci.upper #> 1 x3 ~ x2 1 1 b1 0.354 0.05 7.046 0 0.256 0.452 #> 2 x3 ~ x2 2 2 b1 0.354 0.05 7.046 0 0.256 0.452
lavaan raised a warning about having only one label.

To achieve what you want, explicitly label the parameter in all groups and fix it to zero in some groups manually.
In the following example, c(b1, b2) is used to label the parameter in all groups, and b2 == 0 is used to fix the parameter in the second group to zero.
mod3 <- " x2 ~ x1 x3 ~ c(b1, b2)*x2 b2 == 0 " fit3 <- sem(model = mod3, data = dat, group = "school") filter(parameterEstimates(fit3), lhs == "x3", op == "~") #> lhs op rhs block group label est se z pvalue ci.lower ci.upper #> 1 x3 ~ x2 1 1 b1 0.317 0.071 4.443 0 0.177 0.457 #> 2 x3 ~ x2 2 2 b2 0.000 0.000 NA NA 0.000 0.000

Is this what you want to achieve in the model?

-- Shu Fai

Ryan Castillo

unread,
Jan 8, 2022, 5:48:44 PM1/8/22
to lavaan
Shu Fai,

Thank you so much for your time and response. This is exactly what I am trying to achieve for my model. Your example is exactly what I needed to overcome this roadblock in my analysis. 

Thanks again!!

- R

Terrence Jorgensen

unread,
Jan 10, 2022, 4:43:53 PM1/10/22
to lavaan
You can also simply perform both operations (labeling and values) on the same line:

x3 ~ c(b1, b2)*x2 + c(NA, 0)*x2

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

Shu Fai Cheung

unread,
Jan 10, 2022, 8:12:08 PM1/10/22
to lavaan
Thanks for this tip! I were not aware of this technique. This makes the model specification easier to read!

-- Shu Fai

Terrence Jorgensen

unread,
Jan 11, 2022, 11:40:46 AM1/11/22
to lavaan

Thanks for this tip! I were not aware of this technique. This makes the model specification easier to read!

I agree; that's how I write syntax using semTools::measEq.syntax().  Multiple modifiers is mentioned in the documentation, at the bottom of the ?model.syntax help page.
Reply all
Reply to author
Forward
0 new messages