Colon operator and moderated mediation

114 views
Skip to first unread message

Shu Fai Cheung

unread,
Dec 15, 2021, 1:56:47 AM12/15/21
to lavaan
I would like to have advice on two questions about moderated mediation in lavaan.

I found that, if the b-path (mediator to outcome) is moderated and we use ":" to create the product term, the moderator and the error term of the mediator do not covary. Actually, with fixed.x = TRUE, the default, the product term is treated as a fixed exogenous variable, which should not be the case because one of its component. the mediator, is not  treated as a fixed variable:

library(lavaan)
#> This is lavaan 0.6-9
#> lavaan is FREE software! Please report any bugs.
options(width = 132)
# Example based on: https://lavaan.ugent.be/tutorial/mediation.html

set.seed(1234)
n <- 100
X <- rnorm(n)
M <- .3*X + rnorm(n)
W <- rnorm(n)
Y <- .2*M + .3*W + 0.7*M*W + rnorm(n)
Data <- data.frame(X = X, Y = Y, M = M, W = W)
Data$MW <- Data$M * Data$W
model <-
'
M ~ X
Y ~ M + W + M:W
'
fit <- sem(model, data = Data)
parameterTable(fit)
#>    id lhs op rhs user block group free ustart exo label plabel  start    est    se
#> 1   1   M  ~   X    1     1     1    1     NA   0         .p1.  0.000  0.274 0.103
#> 2   2   Y  ~   M    1     1     1    2     NA   0         .p2.  0.000  0.422 0.096
#> 3   3   Y  ~   W    1     1     1    3     NA   0         .p3.  0.000  0.328 0.106
#> 4   4   Y  ~ M:W    1     1     1    4     NA   0         .p4.  0.000  0.541 0.095
#> 5   5   M ~~   M    0     1     1    5     NA   0         .p5.  0.565  1.054 0.149
#> 6   6   Y ~~   Y    0     1     1    6     NA   0         .p6.  0.931  1.030 0.146
#> 7   7   X ~~   X    0     1     1    0     NA   1         .p7.  0.999  0.999 0.000
#> 8   8   X ~~   W    0     1     1    0     NA   1         .p8.  0.078  0.078 0.000
#> 9   9   X ~~ M:W    0     1     1    0     NA   1         .p9. -0.025 -0.025 0.000
#> 10 10   W ~~   W    0     1     1    0     NA   1        .p10.  0.913  0.913 0.000
#> 11 11   W ~~ M:W    0     1     1    0     NA   1        .p11.  0.032  0.032 0.000
#> 12 12 M:W ~~ M:W    0     1     1    0     NA   1        .p12.  1.142  1.142 0.000
Created on 2021-12-15 by the reprex package (v2.0.1)

Is this behavior intended? To my understanding, the product term should be allowed to covary with the error term of the mediator, as in Model 7 (p.111) of the following paper:

Miles, J. N. V., Kulesza, M., Ewing, B., Shih, R. A., Tucker, J. S., & D’Amico, E. J. (2015). Moderated mediation analysis: An illustration using the association of gender with delinquency and mental health. Journal of Criminal Psychology, 5(2), 99–123. https://doi.org/10.1108/JCP-02-2015-0010

My first question: Is there anyway to use ":" but tell lavaan to add a covariance between the error term of the mediator (M) and the moderator (W)? "M:W ~~ M" and "M ~~ M:W" do not work because the product term is not in the data file.

If not, this can be done by manually creating the product term. However, we need to set fixed.x to FALSE, and we also need to manually add all the covariances, which is prone to human error:

library(lavaan)
#> This is lavaan 0.6-9
#> lavaan is FREE software! Please report any bugs.
options(width = 132)
set.seed(1234)
n <- 100
X <- rnorm(n)
M <- .3*X + rnorm(n)
W <- rnorm(n)
Y <- .2*M + .3*W + 0.7*M*W + rnorm(n)
Data <- data.frame(X = X, Y = Y, M = M, W = W)
Data$MW <- Data$M * Data$W
model2 <-
'
M ~ X
Y ~ M + W + MW
MW ~~ M + W + X
W ~~ M
W ~~ X
'
fit2 <- sem(model2, data = Data, fixed.x = FALSE)
parameterTable(fit2)
#>    id lhs op rhs user block group free ustart exo label plabel start    est    se
#> 1   1   M  ~   X    1     1     1    1     NA   0         .p1. 0.000  0.274 0.103
#> 2   2   Y  ~   M    1     1     1    2     NA   0         .p2. 0.000  0.422 0.101
#> 3   3   Y  ~   W    1     1     1    3     NA   0         .p3. 0.000  0.328 0.107
#> 4   4   Y  ~  MW    1     1     1    4     NA   0         .p4. 0.000  0.541 0.100
#> 5   5   M ~~  MW    1     1     1    5     NA   0         .p5. 0.000  0.347 0.115
#> 6   6   W ~~  MW    1     1     1    6     NA   0         .p6. 0.000  0.032 0.102
#> 7   7   X ~~  MW    1     1     1    7     NA   0         .p7. 0.000 -0.025 0.107
#> 8   8   M ~~   W    1     1     1    8     NA   0         .p8. 0.000  0.093 0.098
#> 9   9   X ~~   W    1     1     1    9     NA   0         .p9. 0.000  0.078 0.096
#> 10 10   M ~~   M    0     1     1   10     NA   0        .p10. 0.565  1.054 0.149
#> 11 11   Y ~~   Y    0     1     1   11     NA   0        .p11. 0.931  1.030 0.146
#> 12 12   X ~~   X    0     1     1   12     NA   0        .p12. 0.499  0.999 0.141
#> 13 13   W ~~   W    0     1     1   13     NA   0        .p13. 0.456  0.913 0.129
#> 14 14  MW ~~  MW    0     1     1   14     NA   0        .p14. 0.571  1.142 0.161
Created on 2021-12-15 by the reprex package (v2.0.1)

Just adding "M ~~ MW" and "M ~~ W" won't work. It seems that this will override the default and all other covariances in the model, e.g., "X ~~ W", will be fixed to zero:

library(lavaan)
#> This is lavaan 0.6-9
#> lavaan is FREE software! Please report any bugs.
options(width = 132)
set.seed(1234)
n <- 100
X <- rnorm(n)
M <- .3*X + rnorm(n)
W <- rnorm(n)
Y <- .2*M + .3*W + 0.7*M*W + rnorm(n)
Data <- data.frame(X = X, Y = Y, M = M, W = W)
Data$MW <- Data$M * Data$W
model2 <-
'
M ~ X
Y ~ M + W + MW
M ~~ MW
M ~~ W
'
fit2 <- sem(model2, data = Data, fixed.x = FALSE)
parameterTable(fit2)
#>    id lhs op rhs user block group free ustart exo label plabel start   est    se
#> 1   1   M  ~   X    1     1     1    1     NA   0         .p1. 0.000 0.274 0.097
#> 2   2   Y  ~   M    1     1     1    2     NA   0         .p2. 0.000 0.422 0.101
#> 3   3   Y  ~   W    1     1     1    3     NA   0         .p3. 0.000 0.328 0.107
#> 4   4   Y  ~  MW    1     1     1    4     NA   0         .p4. 0.000 0.541 0.100
#> 5   5   M ~~  MW    1     1     1    5     NA   0         .p5. 0.000 0.344 0.115
#> 6   6   M ~~   W    1     1     1    6     NA   0         .p6. 0.000 0.083 0.093
#> 7   7   M ~~   M    0     1     1    7     NA   0         .p7. 0.565 1.052 0.149
#> 8   8   Y ~~   Y    0     1     1    8     NA   0         .p8. 0.931 1.030 0.146
#> 9   9   W ~~   W    0     1     1    9     NA   0         .p9. 0.456 0.913 0.129
#> 10 10  MW ~~  MW    0     1     1   10     NA   0        .p10. 0.571 1.142 0.161
#> 11 11   X ~~   X    0     1     1   11     NA   0        .p11. 0.999 0.999 0.141
Created on 2021-12-15 by the reprex package (v2.0.1)

My second question: Is there an option that can force lavaan to set all the covariances between the exogenous variables free, even if we manually set some covariances to free?

Thanks.

Regards,
Shu Fai

Yves Rosseel

unread,
Jun 25, 2022, 8:04:19 AM6/25/22
to lav...@googlegroups.com, Shu Fai Cheung
Another belated reply.

The use of the 'colon' operator is dangerous. It is one of those syntax
'features' that I regret. It was only intended for interaction terms
involving 1) two, 2) exogenous, 3) observed variables. It is much safer
to define the product terms in the data.frame beforehand, and avoid the
use of the colon operator altogether.

However, lavaan dev 0.6-12 will now check the status (dependent or
independent) of both variables in the interaction term, and if either
one (or both) are dependent, the interaction term is no longer treated
as exogenous (ie., it will not appear in the output of lavNames(fit,
"ov.x"))

As a result, it shouldn't be a problem to add the residual covariance
between the mediator (M) and the interaction term (M:W), even if fixed.x
= TRUE.

This term will not be added automatically, as M:W does not appear in
either lavNames(,"ov.x") or lavNames(,"ov.y").

As for the second question ("Is there an option that can force lavaan to
set all the covariances between the exogenous variables free, even if we
manually set some covariances to free?"), the answer is: "no".

If variables are correctly identified as being exogenous, there is no
need. Once you intervene manually, the user is responsible for adding
all the needed covariances. This may be error-prone, but the 'automagic'
completion of model syntax can only go so far.

Yves.
> /Journal of Criminal Psychology/, /5/(2), 99–123.
> https://doi.org/10.1108/JCP-02-2015-0010
> --
> 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 on the web visit
> https://groups.google.com/d/msgid/lavaan/3b0273d9-0a35-4fcc-8742-6723cdd35e1an%40googlegroups.com
> <https://groups.google.com/d/msgid/lavaan/3b0273d9-0a35-4fcc-8742-6723cdd35e1an%40googlegroups.com?utm_medium=email&utm_source=footer>.

--
Yves Rosseel
Department of Data Analysis, Ghent University
Reply all
Reply to author
Forward
0 new messages