Moderated mediation with two moderators and two independent variables

318 views
Skip to first unread message

F Makrani

unread,
Jun 16, 2023, 7:38:49 AM6/16/23
to lavaan
I have a basic question on conducting a moderated mediation using Lavaan. I have the following conceptual model: (mis)perceptions present two independent variables (Inschatten.algemeen and migratievermogen). 


Afbeelding1.png

I tried the following code:
# Define the model syntax
model <- '
  # Direct effects
  Supporttime2 ~ c1 * migratievermogen + c2 * Inschatten.algemeen
  Supporttime1 ~ b1 * migratievermogen + b2 * Inschatten.algemeen
 
  # Mediation effect
  Supporttime2 ~ d * Supporttime1

  # Moderation effects
  Supporttime1 ~ m1 * migratievermogen * ordereffect
  Supporttime1 ~ m2 * Inschatten.algemeen * ordereffect
  Supporttime2 ~ i * Supporttime1 * Information
'

# Fit the model
fit <- lavaan::sem(model, data = data_num)

# Summarize the results
summary(fit, standardized = TRUE)

Error in lavParseModelString(model) : lavaan ERROR: duplicate model element in: Supporttime1~m2*Inschatten.algemeen*ordereffect


Any tips would be helpful!

Thanks in advance.

Shu Fai Cheung (張樹輝)

unread,
Jun 16, 2023, 8:17:28 AM6/16/23
to lavaan
In the following lines, I believe you want to create product terms:

  # Moderation effects
  Supporttime1 ~ m1 * migratievermogen * ordereffect
  Supporttime1 ~ m2 * Inschatten.algemeen * ordereffect
  Supporttime2 ~ i * Supporttime1 * Information

We do this in lm() but this approach is not supported in lavaan. Instead, the colon operator, ":", is for this purpose. Therefore, the following lines will "work":

  Supporttime1 ~ m1 * migratievermogen:ordereffect
  Supporttime1 ~ m2 * Inschatten.algemeen:ordereffect
  Supporttime2 ~ i * Supporttime1:Information

However, this may not be a good way to set the product term, at least not in previous versions of lavaan. You can refer to this post:


A more reliable way to form the product terms are to create them ourselves. E.g.,

data_num$migratievermogen_ordereffect <- data_num$ migratievermogen * data$num$ordereffect
data_num$Inschatten.algemeen_ordereffect <- data_num$Inschatten.algemeen * data_num$ordereffect
data_num$Supporttime1_Information <-  data_num$Information * data_num$Information

Then you can include the product terms in the model syntax:

  Supporttime1 ~ m1 * migratievermogen_ordereffect
  Supporttime1 ~ m2 * Inschatten.algemeen_ordereffect
  Supporttime2 ~ i * Supporttime1_Information

Personally, I would avoid using the colon operator. It is easy to work with the product term if it is an observed variable instead of a variable created internally:


But the comment from Yves was posted last summer. I don't know whether it still applies to the current version of lavaan. Maybe there are some changes in lavaan that makes the colon operator a better option.

Hope this helps.

Regards,
Shu Fai

F Makrani

unread,
Jun 16, 2023, 8:43:53 AM6/16/23
to lavaan
Many thanks for your quick response and explanation! I tried your second suggestion and it worked, I will add the results. Would you say this is the best way to test this type of moderated mediation or suggest another way?

> model <- '

+   # Direct effects

+   Supporttime2 ~ c1 * migratievermogen + c2 * Inschatten.algemeen

+   Supporttime1 ~ b1 * migratievermogen + b2 * Inschatten.algemeen

+   

+   # Mediation effect

+   Supporttime2 ~ d * Supporttime1

+   

+   # Moderation effects

+   Supporttime1 ~ m1 * migratievermogen_ordereffect

+   Supporttime1 ~ m2 * Inschatten.algemeen_ordereffect

+   Supporttime2 ~ i * Supporttime1_Information

+ ' 

> # Fit the model

> fit <- lavaan::sem(model, data = data_num)

> # Summarize the results

> summary(fit, standardized = TRUE)

lavaan 0.6.15 ended normally after 2 iterations

 

  Estimator                                         ML

  Optimization method                           NLMINB

  Number of model parameters                        10

 

                                                  Used       Total

  Number of observations                           413         414

 

Model Test User Model:

                                                     

  Test statistic                                 3.170

  Degrees of freedom                                 3

  P-value (Chi-square)                           0.366

 

Parameter Estimates:

 

  Standard errors                             Standard

  Information                                 Expected

  Information saturated (h1) model          Structured

 

Regressions:

                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv

  Supporttime2 ~                                              

    mgrtvrmgn (c1)   -0.001    0.007   -0.070    0.944   -0.001

    Inschttn. (c2)    0.014    0.007    1.830    0.067    0.014

  Supporttime1 ~                                              

    mgrtvrmgn (b1)    0.041    0.023    1.747    0.081    0.041

    Inschttn. (b2)   -0.014    0.029   -0.479    0.632   -0.014

  Supporttime2 ~                                              

    Supprttm1  (d)    1.001    0.018   55.640    0.000    1.001

  Supporttime1 ~                                              

    mgrtvrmg_ (m1)    0.026    0.024    1.103    0.270    0.026

    Inschtt._ (m2)   -0.076    0.039   -1.951    0.051   -0.076

  Supporttime2 ~                                              

    Spprtt1_I  (i)   -0.029    0.035   -0.811    0.417   -0.029

  Std.all

        

   -0.001

    0.032

        

    0.103

   -0.035

        

    0.943

        

    0.099

   -0.193

         

   -0.014

 

Variances:

                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv

   .Supporttime2      0.129    0.009   14.370    0.000    0.129

   .Supporttime1      0.955    0.066   14.370    0.000    0.955

  Std.all

    0.116

    0.964

 

Best regards,

Farah

Op vrijdag 16 juni 2023 om 14:17:28 UTC+2 schreef shufai...@gmail.com:

Shu Fai Cheung (張樹輝)

unread,
Jun 16, 2023, 9:05:03 AM6/16/23
to lavaan
Hi Farah,

It seems that you are using the default options. You did not use FIML and similar methods to handle missing data. So you don't have missing data or are OK with listwise deletion (the default in lavaan). You also use ML, the default estimator. You did not use MLR or similar methods to handle nonnormality. You also did not set any variables as ordinal (using ordered). Based on the diagram, your model is supposed to be a saturated model, though it is not, probably because of some covariances or error covariances fixed to zero.

If you do want to use SEM, even for this apparently simple (and common) model, it is actually not as simple as it looks. You can take look at the examples in this 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

Although the following paper is on multiple regression, what they presented about covariances may still apply to SEM:

Preacher, K. J., Rucker, D. D., & Hayes, A. F. (2007). Addressing moderated mediation hypotheses: Theory, methods, and prescriptions. Multivariate Behavioral Research, 42(1), 185–227. https://doi.org/10.1080/00273170701341316

If you do not have anything that must be done using SEM, maybe you can just use the regression-based approach for this model. It is old, but probably good enough for your case.

Hope this helps.

-- Shu Fai

F Makrani

unread,
Jun 16, 2023, 9:13:48 AM6/16/23
to lavaan
Many thanks again! I will look into the references you shared. 

Best regards,

Farah

Op vrijdag 16 juni 2023 om 15:05:03 UTC+2 schreef shufai...@gmail.com:
Reply all
Reply to author
Forward
0 new messages