Moderated mediation

3,155 views
Skip to first unread message

Marcos Sanches

unread,
Nov 8, 2012, 10:49:28 AM11/8/12
to lav...@googlegroups.com
I am trying to fit a moderated mediation model where my moderator is a 3 levels categorical variable. This is my syntax:

model2 <- '#Regressions

 Y ~  c*X + b*M

 M ~ a*X

 #variances and covariances

 Y ~~ Y

 M ~~ M

#indirect effect

ab := a*b

#total effect

tot := c + (a*b) '


fit3 <- sem(model2, data = semdata, group = "Treatment", test = "bootstrap")
summary(fit3)

This does not give me the defined parameter (indirect effect) ab by group. I would like to access it by group so that I can compare and see if the indirect effect depends on group. Is there a way to get the indirect effect for each group?

Thanks a lot!

Marcos






yrosseel

unread,
Nov 9, 2012, 3:52:59 AM11/9/12
to lav...@googlegroups.com
You have separate regression coefficient per group. So there is no
single 'a' or 'b' or 'c', but you have 'a1,a2,a3', 'b1,b2,b3' and
'c1,c2,c3'.

You can adapt your syntax as follows:

Y ~ c(c1,c2,c3)*X + c(b1,b2,b3)*M
M ~ c(a1,a2,a3)*X
...
ab1 := a1*b1
ab2 := a2*b2
ab3 := a3*b3

tot1 := c1 + (a1*b1)
tot2 := c2 + (a2*b2)
tot3 := c3 + (a3*b3)



Hope this helps,

Yves.

Marcos Sanches

unread,
Nov 9, 2012, 9:17:07 AM11/9/12
to lav...@googlegroups.com
Great, totally makes sense, thanks!



--
You received this message because you are subscribed to the Google Groups "lavaan" group.
To post to this group, send email to lav...@googlegroups.com.
Visit this group at http://groups.google.com/group/lavaan?hl=en.



ya

unread,
Nov 11, 2012, 7:37:02 AM11/11/12
to yrosseel, lavaan
Hi,
 
What if the moderator is a continuous variable? how to calculate the indirect effect?
 
Thank you.
 

ya

yrosseel

unread,
Nov 12, 2012, 1:34:31 PM11/12/12
to xinxi813, lavaan
On 11/11/2012 01:37 PM, ya wrote:
> Hi,
> What if the moderator is a continuous variable? how to calculate the
> indirect effect?

You need to add the interaction term (or interaction terms) to both the
data.frame and the model syntax, and this creates an additional set of
regressions coefficients, which may be needed for the indirect effects.

See

Preacher, K. J., Rucker, D. D., & Hayes, A. F. (2007). Addressing
moderated mediation hypotheses: Theory, methods, and prescriptions.
Multivariate Behavioral Research, 42, 185-227. [Supplementary SPSS
macro, Mplus code, and Mathematica code]

Yves.

Jesse Gervais

unread,
Nov 19, 2013, 12:37:14 PM11/19/13
to lav...@googlegroups.com

Hi there,

 

Is it possible to do a moderated mediation where I have two categorical independent variables (two categories), one categorical mediator (5 categories), and where the relationship between the mediator and the dependant variable is moderated by the two categorical independent variables   

Starting from the previous syntax in this post, I would say that, it should be something like:

Y ~ c*X + c(b1,b2,b3, b4, b5)*M 
M ~ c(a1,a2,a3,a4, a5)*X 


... 
ab1 := a1*b1 
ab2 := a2*b2 
ab3 := a3*b3 

ab4 := a4*b4 

ab5 := a5*b5 



tot1 := c1 + (a1*b1) 
tot2 := c2 + (a2*b2) 
tot3 := c3 + (a3*b3) 

tot4 := c4 + (a4*b4)

tot5 := c5 + (a4*b4)

 

 

However, I don’t know how to add, if it is possible, the other independent variable??


If it is not possible (or even if it s possible), can I just create a latent variable with the two independent variables (I have a theoretical justification for it), and just do:

 

 X =~ IND1 + IND2

Y ~ c*X + c(b1,b2,b3, b4, b5)*M 
M ~ c(a1,a2,a3,a4, a5)*X 


... 
ab1 := a1*b1 
ab2 := a2*b2 
ab3 := a3*b3 

ab4 := a4*b4 

ab5 := a5*b5 



tot1 := c1 + (a1*b1) 
tot2 := c2 + (a2*b2) 
tot3 := c3 + (a3*b3) 

tot4 := c4 + (a4*b4)

tot5 := c5 + (a4*b4)

 

 

Thank you!

yrosseel

unread,
Nov 20, 2013, 2:48:06 AM11/20/13
to lav...@googlegroups.com
On 11/19/2013 06:37 PM, Jesse Gervais wrote:
> Hi there,
>
> Is it possible to do a moderated mediation where I have two categorical
> independent variables (two categories), one categorical mediator (5
> categories), and where the relationship between the mediator and the
> dependant variable is moderated by the two categorical independent
> variables
>
> Starting from the previous syntax in this post, I would say that, it
> should be something like:
>
> Y ~ c*X + c(b1,b2,b3, b4, b5)*M
> M ~ c(a1,a2,a3,a4, a5)*X

So you seem to use the approach where the (cateogrical) mediator is used
as the 'grouping' factor in a multiple group analysis.

In this case, since you have two (binary) independents, you can try
something along the lines of:

Y ~ c1*X1 + +c2*X2 + c(b1,b2,b3, b4, b5)*M
M ~ c(a1,a2,a3,a4, a5)*X1 + c(d1,d2,d3,d4,d5)*X2

Yves.

Jesse Gervais

unread,
Nov 21, 2013, 4:22:03 PM11/21/13
to lav...@googlegroups.com
Thank you! 

David Disabato

unread,
Mar 11, 2015, 2:07:56 AM3/11/15
to lav...@googlegroups.com
Hi Yves,

I am trying to run a moderated mediation model in lavaan where I have a numeric IV, mediator, and DV with a dichotomous moderator. I thought it would make the most sense to use a multiple-groups analysis with each level of the moderator as a group. It is my understanding that in a multiple-groups analysis you can test for moderation by seeing if model fit significantly decreases (i.e., chi-square difference test) when you constrain certain parameter estimates across groups to be equal. I would like to constrain effects I have created in my lavaan model code such as the total effect (i.e., total := a*b + cp), indirect effect (i.e., indirect := a*b), and direct effect (direct := cp). However, I keep getting an error when I attempt to constrain these "user defined" parameter estimates. Is it possible to do so in lavaan? If yes, how?

If no, how would you recommend testing for moderated mediation in lavaan? Would you constrain the a,b, and c-prime path coefficients all together to test for moderation of the total effect, constrain only the a and b path coefficients together to test for moderation of the indirect effect, and constrain only the c-prime path coefficient to test for moderation of the direct effect?

Thank you in advance for any help.

-David

Terrence Jorgensen

unread,
Mar 12, 2015, 1:22:30 PM3/12/15
to lav...@googlegroups.com
I can't speak to whether it's possible to constrain user-defined parameters to equality (I would assume not because they are merely functions of other parameters).  But you have the correct idea about constraining a and b to test moderation of the indirect effect, etc.

Terry


yrosseel

unread,
Mar 13, 2015, 9:31:07 AM3/13/15
to lav...@googlegroups.com
On 03/11/2015 07:07 AM, David Disabato wrote:
> I would
> like to constrain effects I have created in my lavaan model code such as
> the total effect (i.e., total := a*b + cp), indirect effect (i.e.,
> indirect := a*b), and direct effect (direct := cp). However, I keep
> getting an error when I attempt to constrain these "user defined"
> parameter estimates. Is it possible to do so in lavaan? If yes, how?

If you have two groups, you should use group-specific labels, as in

Y ~ c(c1,c2)*X + c(b1,b2)*M
M ~ c(a1,a2)*X

ab1 := a1*b1
ab2 := a2*b2

and you should be able to constrain the user-specified variables across
groups:

ab1 == ab2

As an example, this works in 0.5-17 (using the HolzingerSwineford1939 data):

model <- '
x1 ~ c(c1,c2)*x2 + c(b1,b2)*x3
x3 ~ c(a1,a2)*x2

ab1 := a1*b1
ab2 := a2*b2

ab1 == ab2
'

fit <- sem(model, data = HolzingerSwineford1939, group = "school")
summary(fit)

Yves.

Bryan Victor

unread,
Jul 27, 2015, 9:14:36 PM7/27/15
to lavaan, yros...@gmail.com
Hi Yves,

I would like to calculate the conditional indirect effects of X on Y given a set of values for the moderator (W).  Both X and the moderator are continuous.  Could you provide some direction for structuring the model syntax?

Bryan 

Terrence Jorgensen

unread,
Jul 28, 2015, 6:36:24 AM7/28/15
to lavaan, bryan...@gmail.com
I would like to calculate the conditional indirect effects of X on Y given a set of values for the moderator (W).  Both X and the moderator are continuous.  Could you provide some direction for structuring the model syntax?

Assuming X and W are both observed variables, you can calculate the product term (XW) in your data.frame and simply add the product term (X-W interaction) to the models for M and Y in Yves' example earlier in this thread (but a single-group version, since your moderator is continuous).

model <- ' 
  Y ~ c*X + cw*XW + b*M
  M ~ a*X + aw*XW
  ## indirect and total effects, conditional on W == 0
  ab0 := a*b            # + 0*aw*b
  total0 := ab0 + c     # + 0*cw
  ## indirect and total effects, conditional on W == 1
  ab1 := ab0 + 1*aw*b
  total1 := ab1 + c + 1*cw
  ## indirect and total effects, conditional on W == 2
  ab2 := ab0 + 2*aw*b
  total2 := ab2 + c + 2*cw
'


Terry

Lianne Aarntzen

unread,
Oct 20, 2015, 4:21:53 AM10/20/15
to lavaan

Hello,

Thank you for the packagelavaan.

I am just a beginner in R and also I do not have much knowledge about structural equation modelling. I am trying to increase my knowledge now by reading a lot of articles.

I am trying to test this model below and I wrote this script. Is it possible to provide me with some feedback if I specified the model correctly? 

Theoretical model (see picture)








Script:
#Create interaction variable
LofData$I_PartPerSacrifice <- LofData$PartPerSacrifice * LofData$WFCtotal

#Covariance between PartPerSacrifice and WFCtotal
WFCtotal ~~ I_PartPerSacrifice

#Regression model

model3 =model3 ='
DistancingVrouw ~ c1*WFCtotal + cw*I_PartPerSacrifice + b1*PerSacrifice
PerSacrifice ~ a1*WFCtotal + aw*I_PartPerSacrifice

#Indirect effects and total effect, conditional on I_PartPerSacrifice == 0.
Indirect1:= a1*b1
total1 := c + (a1*b1)

#Indirect effects and total effect, conditional on I_PartPerSacrifice == 1.
Indirect2:= indirect1 + 1*aw*b1
Total2 := indirect2 + c + 1*cw

#Indirect effects and total effect, conditional on I_PartPerSacrifice == 2.
Indirect3:= indirect2 + 2*aw*b1
total := indirect3 + c +2*cw
'
model.fit3 = sem(model3, data=LofData)
summary(model.fit3, standardized=TRUE, fit.measures=TRUE, rsq=TRUE)

library (semPlot)
semPaths(model.fit3,'model', 'est', style='ram')


Terrence Jorgensen

unread,
Oct 21, 2015, 5:36:19 AM10/21/15
to lavaan
Script:
#Create interaction variable
LofData$I_PartPerSacrifice <- LofData$PartPerSacrifice * LofData$WFCtotal

This should be in your R syntax, but not part of the character string defining the model syntax.  So it looks correct so far.
 
#Covariance between PartPerSacrifice and WFCtotal
WFCtotal ~~ I_PartPerSacrifice

This is model syntax, and should be part of the character string "model3".  You could also leave it out and just specify the option sem(..., fixed.x = FALSE) when you run your model.


model3 =model3 ='
DistancingVrouw ~ c1*WFCtotal + cw*I_PartPerSacrifice + b1*PerSacrifice
PerSacrifice ~ a1*WFCtotal + aw*I_PartPerSacrifice

You also need to include the main effect of PartPerSacrifice on DistancingVrouw and on PerSacrifice, otherwise the "interaction" term doesn't mean what you think it does.  You need to label those additional effects (e.g., a2 and c2) so you can include them in your equations for Total effects below

#Indirect effects and total effect, conditional on I_PartPerSacrifice == 0.
Indirect1:= a1*b1
total1 := c + (a1*b1)

You define the direct effect of WFCtotal on DistancingVrouw as "c1", not "c", so you need to update this and all formulas for indirect paths in your syntax.

Terry

Lianne Aarntzen

unread,
Oct 21, 2015, 8:00:39 AM10/21/15
to lavaan
Dear Terry,

Thank you so much, this really helps!

Op woensdag 21 oktober 2015 11:36:19 UTC+2 schreef Terrence Jorgensen:

Jessica Fritz

unread,
May 13, 2016, 9:46:18 AM5/13/16
to lavaan
Hi everyone,

I think I have a similar question than Lianne, only somewhat simpler. 

I tried to inlcude a covariate in my mediation model. Thus I do not have a moderated mediaton model, but only want to correct the whole model (all mediation pathes: a,b and c) with the same covariate. I thought that I simply could add the covariate as 'second predictor' to the model, because I thought that this would be the same as running three regressions instead of 1 SEM. But after having seen Lianne's script I am wondering whether my model is too simple and whether I need to include the covariate into the calculation of the indirect and the total effect, as well?

So far I used the following script:

Model <-'Yvar ~ c*Xvar
Mvar ~ a*Xvar
Yvar ~ b*Mvar
Yvar ~ covariate
Mvar ~ covariate
ab := a*b
total := c + (a*b)'

Thank you for your help,

Jes

Terrence Jorgensen

unread,
May 16, 2016, 4:44:05 PM5/16/16
to lavaan
This is a general SEM question you could post to SEMNET.  But I think your syntax for calculating the indirect and total effect of X on Y (via M) is valid even with the additional covariate.

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


Jessica Fritz

unread,
May 17, 2016, 5:17:51 AM5/17/16
to lavaan
Thank you very much Terrence!

Andrew Fox

unread,
Aug 7, 2018, 3:29:40 AM8/7/18
to lavaan
Hi Terry and Yves,

I'm trying to utilize the code you provided to fit a moderated mediation in lavaan to calculate the conditional indirect effects of X (agencyc) on Y (posAffect) through M (intMotivc) given moderator W (negAffectc), which is operating only on the a path.  All variables are continuous, and all predictors are centered.

Here's a bit of the data for reference:

           XW    agencyc    negAffectc      intMotivc
1 3.833333  1.3215196 -0.59085684  0.9770378
2 4.512269  0.3770862 -0.02892351 -0.2855289
3 1.777767 -0.7340471 -0.59085684 -0.3562955
4 5.918972  0.2200196  0.57580982  0.3549378
5 7.777750  0.5992862  0.90914316  0.8103711


My code is as follows:

modMed <- '
  #direct effects
  posAffect ~ c*agencyc + b*intMotivc
  intMotivc ~ a1*agencyc + a2*negAffectc + a3*XW
  #indirect and total effects, conditional on negAffectc == 0
  ab0 := a1*b
  total0 := ab0 + c
  #indirect and total effects, conditional on negAffectc == 1
  ab1 := a1*b + a3*b
  total1 := ab1 + c
  #indirect and total effects, conditional on negAffectc == 2
  ab2 := a1*b + 2*a3*b
  total2 := ab2 + c
  '
fsem4 <- sem(modMed, data = dat, se = "bootstrap", bootstrap = 1000 
summary(modMed)

But, when I run this code, what appears in the output following the summary is: 

\n  #direct effects\n  posAffect ~ c*agencyc + b*intMotiv\n  intMotiv ~ a1*agencyc + a2*negAffect + a3*XW\n  #indirect and total effects, conditional on negAffect == 0\n  ab0 := a1*b\n  total0 := ab0 + c\n  #indirect and total effects, conditional on negAffect == 1\n  ab1 := a1*b + a3*b\n  total1 := ab1 + c\n  #indirect and total effects, conditional on negAffect == 2\n  ab2 := a1*b + 2*a3*b\n  total2 := ab2 + c\n                        
                       1 
I'm not sure where I'm going wrong, I don't get any parameter output, and I didn't have any issues when fitting mediation models in lavaan without any moderators.  Is there any assistance you might be able to provide to help?

A further question I have, is how I might be able to compute my conditional indirect effects at percentiles of the moderator (or standard deviations), as is done with PROCESS?  I'm not 100% clear what we are conditioning here in this code, except for when W = 0 and W = 1.

Thanks so much.

Best,
Andrew

Terrence Jorgensen

unread,
Aug 7, 2018, 8:20:51 AM8/7/18
to lavaan
when I run this code ... I don't get any parameter output

summarize your fitted model, not the character string that specifies your model.

summary(fsem4 )


A further question I have, is how I might be able to compute my conditional indirect effects at percentiles of the moderator (or standard deviations), as is done with PROCESS?  I'm not 100% clear what we are conditioning here in this code, except for when W = 0 and W = 1.

Assuming you W is negAffectc, you can inspect your data to see what values represent the quantiles you are interested in.  For example, to get the 10th, 50th, and 90th percentiles:

quantile(dat$negAffectc, probs = c(.1, .5, .9))

Then you can write those values into your syntax.

Andrew Fox

unread,
Aug 22, 2018, 7:06:16 PM8/22/18
to lavaan
Thank you so much, this was so helpful!!!

Muk Okuyan

unread,
Apr 8, 2019, 2:20:32 PM4/8/19
to lavaan
Hi Terrence,

I'm using the code you provided here to estimate a moderated mediation with two serial mediators. All variables are continuous. The regression equation you have in the probing interaction line (ab0 := a*b   # + 0*aw*b) suggest adding a product of w, aw and b paths, and not products of b path separately with a, aw and w paths (which is more intuitive to me). I wrote my code in accordance with the former style. I wanted to double check if this is correct. Below is the model.

Here is my code:

ModMed <- '
                   Policy ~ c*sdo.c + b2*Discrim + d*Legit
                   Discrim ~ a_2*sdo.c + b1*Legit
                   Legit ~ a*sdo.c + w*threat.c + aw*sdo_threat

                  IndirectLeg := (a*b1)+(w*aw*b1)    #or should this be (a*b1)+(w*b1)+(aw*b1)
                  IndirectDis := a_2*b2

                  Total := c + (a*b1)+(w*aw*b1)+(a_2*b2)     #so, this would be c + (a*b1)+(a*b1)+(w*b1)+(aw*b1)+(a_2*b2)

Thank you so much in advance!

Best,
Muk

Terrence Jorgensen

unread,
Apr 10, 2019, 8:32:08 AM4/10/19
to lavaan
The regression equation you have in the probing interaction line (ab0 := a*b   # + 0*aw*b) suggest adding a product of w, aw and b paths, and not products of b path separately with a, aw and w paths

No, read this primer on moderation:


ModMed <- '
                   Policy ~ c*sdo.c + b2*Discrim + d*Legit
                   Discrim ~ a_2*sdo.c + b1*Legit
                   Legit ~ a*sdo.c + w*threat.c + aw*sdo_threat

                  IndirectLeg := (a*b1)+(w*aw*b1)    #or should this be (a*b1)+(w*b1)+(aw*b1)
                  IndirectDis := a_2*b2

                  Total := c + (a*b1)+(w*aw*b1)+(a_2*b2)     #so, this would be c + (a*b1)+(a*b1)+(w*b1)+(aw*b1)+(a_2*b2)

Also read more about mediation.  Serial mediation means you have to calculate the product of all paths from a predictor to the outcome.  So the indirect effects of sdo.c on policy are:
  • via Legit == a*d 
  • via Discrim ==  a_2*b2 # already correct
  • via Legit then Discrim == a*b1*b2
  • (so the Total indirect effect would be the sum:  a*d + a_2*b2 + a*b1*b2)
All this is when holding Threat constant at 0, so its moderating effect is "absent" from the equations.  When Threat != 0, you need to adjust the a path accordingly, because that is the only path that is moderated by Threat.  But the "w" path never enters the equations (that only adjusts the simple intercepts).  You just need to think of the "A" path as itself being an equation rather than a single number

A = a + aw*Threat

So to keep your mind straight, you could just define A at different values of Threat:

a_wm1 := a + aw*(-1)
a_w0
:= a # + aw*0
a_wp1
:= a + aw*1

Then take turns plugging those into the indirect-effect equations above.

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

Mukadder Okuyan

unread,
Apr 12, 2019, 1:14:45 PM4/12/19
to lav...@googlegroups.com
Hi Terrence,

This is very helpful, thank you for the links and explaining the correct code!

Best,
Muk

--
You received this message because you are subscribed to a topic in the Google Groups "lavaan" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/lavaan/RW_3TMARGhY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to lavaan+un...@googlegroups.com.

To post to this group, send email to lav...@googlegroups.com.
Visit this group at https://groups.google.com/group/lavaan.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages