Calculating Effect Size Moderated Mediation Model

154 views
Skip to first unread message

F Makrani

unread,
Jun 29, 2023, 10:59:13 AM6/29/23
to lavaan
I am trying to calculate the effect size of my moderated mediation model, but I keep getting errors. This is the code that I have tried:

# Define the model
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)

obs.vars <- c("migratievermogen", "Inschatten.algemeen", "Supporttime1",
              "Supporttime2", "migratievermogen_ordereffect",
              "Inschatten.algemeen_ordereffect", "Supporttime1_Information")

my.cor <- cov(data_num[obs.vars], use = "complete.obs")
calEffSizes(model, n = 414, Cov=my.cor)

This is the error: Error in fit@Model@def.function(.x. = x) : unused argument (.x. = x)

Shu Fai Cheung (張樹輝)

unread,
Jun 29, 2023, 9:38:47 PM6/29/23
to lavaan
From the help page of metaSEM::calEffSizes(), it is for computing the user defined parameters and their vcov.

Therefore, you need to have at least one parameters defined by ":=", as in the help page example.

By the way, perhaps you do not need to use calEffSizes? The estimates are identical to those computed by lavaan, so are the SEs (returned in the output) and the vcov (returned by lavInspect with what = "vocv.def"), as illustrated below.

``` r
# Adapted from the example of calEffSizes

library(metaSEM)
#> Loading required package: OpenMx
#> "SLSQP" is set as the default optimizer in OpenMx.
#> mxOption(NULL, "Gradient algorithm") is set at "central".
#> mxOption(NULL, "Optimality tolerance") is set at "6.3e-14".
#> mxOption(NULL, "Gradient iterations") is set at "2".
library(lavaan)
#> This is lavaan 0.6-15
#> lavaan is FREE software! Please report any bugs.

obs.vars <- c("BEH", "BI", "ATT")

## Select one study from Cooke16 for illustration
my.cor <- Cooke16$data[[4]][obs.vars, obs.vars]
my.n  <- Cooke16$n[4]

## Effect sizes: indirect effect and direct effect
model <- "BEH ~ c*ATT + b*BI
          BI ~ a*ATT
          ## Indirect effect
          Ind := a*b
          Dir := c"

calEffSizes(model=model, n=my.n, Cov=my.cor, lavaan.output=FALSE)
#> $ES
#>          Ind          Dir
#>  0.137665998 -0.007665998
#>
#> $VCOV
#>               Ind           Dir
#> Ind  0.0014946061 -0.0008943229
#> Dir -0.0008943229  0.0058798353

## Return the lavaan fitted model
fit <- calEffSizes(model=model, n=my.n, Cov=my.cor, lavaan.output=TRUE)
lavaan::summary(fit)
#> lavaan 0.6.15 ended normally after 1 iteration
#>
#>   Estimator                                         ML
#>   Optimization method                           NLMINB
#>   Number of model parameters                         5
#>
#>   Number of observations                           176
#>
#> Model Test User Model:
#>                                                      
#>   Test statistic                                 0.000
#>   Degrees of freedom                                 0
#>
#> Parameter Estimates:
#>
#>   Standard errors                             Standard
#>   Information                                 Expected
#>   Information saturated (h1) model          Structured
#>
#> Regressions:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>   BEH ~                                              
#>     ATT        (c)   -0.008    0.077   -0.100    0.920
#>     BI         (b)    0.353    0.077    4.603    0.000
#>   BI ~                                                
#>     ATT        (a)    0.390    0.069    5.619    0.000
#>
#> Variances:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>    .BEH               0.877    0.094    9.381    0.000
#>    .BI                0.848    0.090    9.381    0.000
#>
#> Defined Parameters:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>     Ind               0.138    0.039    3.561    0.000
#>     Dir              -0.008    0.077   -0.100    0.920
   
lavaan::parameterestimates(fit)  
#>   lhs op rhs label    est    se      z pvalue ci.lower ci.upper
#> 1 BEH  ~ ATT     c -0.008 0.077 -0.100   0.92   -0.158    0.143
#> 2 BEH  ~  BI     b  0.353 0.077  4.603   0.00    0.203    0.503
#> 3  BI  ~ ATT     a  0.390 0.069  5.619   0.00    0.254    0.526
#> 4 BEH ~~ BEH        0.877 0.094  9.381   0.00    0.694    1.061
#> 5  BI ~~  BI        0.848 0.090  9.381   0.00    0.671    1.025
#> 6 ATT ~~ ATT        1.000 0.000     NA     NA    1.000    1.000
#> 7 Ind := a*b   Ind  0.138 0.039  3.561   0.00    0.062    0.213
#> 8 Dir :=   c   Dir -0.008 0.077 -0.100   0.92   -0.158    0.143

es <- calEffSizes(model=model, n=my.n, Cov=my.cor, lavaan.output=FALSE)

# The SEs are the same
print(lavaan::parameterestimates(fit, ci = FALSE)[7:8, ], nd = 8)
#>   lhs op rhs label       est         se           z     pvalue
#> 7 Ind := a*b   Ind  0.137666 0.03866014  3.56092903 0.00036954
#> 8 Dir :=   c   Dir -0.007666 0.07668008 -0.09997379 0.92036514
sqrt(diag(es$VCOV))
#>        Ind        Dir
#> 0.03866014 0.07668008

# The vcov is the same
print(lavInspect(fit, "vcov.def"), nd = 12)
#>               Ind           Dir
#> Ind  0.0014946061              
#> Dir -0.0008943229  0.0058798353
es$VCOV
#>               Ind           Dir
#> Ind  0.0014946061 -0.0008943229
#> Dir -0.0008943229  0.0058798353
```

<sup>Created on 2023-06-30 with [reprex v2.0.2](https://reprex.tidyverse.org)</sup>

Hope this helps.

-- Shu Fai

Shu Fai Cheung (張樹輝)

unread,
Jun 29, 2023, 9:59:51 PM6/29/23
to lavaan
By the way, you may need to check your model. For a product term, we need to include the lower order term.

E.g., if migratievermogen_ordereffect is the product of migratievermogen and ordereffect, then you also need to include both  migratievermogen and ordereffect in the same regression equation.

I am not 100% certain the following correctly represent what you want, but this may give you an idea of what I meant:

```
# Define the model
model <- '
  Supporttime1 ~ b1 * migratievermogen + b2 * Inschatten.algemeen + ordereffect +
                 m1 * migratievermogen_ordereffect + m2 * Inschatten.algemeen_ordereffect
  Supporttime2 ~ d * Supporttime1 + c1 * migratievermogen + c2 * Inschatten.algemeen + Information +
                 i * Supporttime1_Information
'
```

The equation is long and not as organized as your version. However, it is easier for checking if any required terms are missing.

Note that you also need to check whether any covariances need to be added manually. This may be a little complicated because both the a-path and the b-path are moderated in your model. See Model 7 of the following paper for an example:

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

Miles and others also illustrated how to use ":=" to define conditional indirect effect.

For the covariances to be added, you an also read the following papers. They discussed some complicated models but also included examples similar to your model:

Kwan, J. L. Y., & Chan, W. (2018). Variable system: An alternative approach for the analysis of mediated moderation. Psychological Methods, 23(2), 262–277. https://doi.org/10.1037/met0000160

Hope this helps.

-- Shu Fai

Shu Fai Cheung (張樹輝)

unread,
Jun 30, 2023, 12:06:57 AM6/30/23
to lavaan
The following sample code may also be useful:


The example illustrate how to compute the conditional indirect effect using lavaan syntax. All the steps are done in lavaan: Get the SDs and means of the moderators using lavaan syntax, and then compute the indirect effects for different values of the moderators.

However, note that the example didn't have any covariances manually added. You may need to check Miles et al. as well as Kwan and Chan on what to add.

-- Shu Fai
Reply all
Reply to author
Forward
0 new messages