You are here

Moderator analyses in OSMASEM

20 posts / 0 new
Last post
Dabiriyan's picture
Offline
Joined: 09/30/2019 - 07:42
Moderator analyses in OSMASEM
AttachmentSize
Binary Data Dabiriyan.sav1.95 KB
Binary Data Dabiriyan.R11.14 KB

Dear Mike & colleagues,
I conducted moderator analyses with OSMASEM with several moderators. When I performed OSMASEM with these moderators simultaneously and separately, it showed different estimates for moderators. Which one should be preferred?

I attached R-code and data.

Thanks for your time and patience.

Mike Cheung's picture
Offline
Joined: 10/08/2009 - 22:37
Dear Dabiriyan,

Dear Dabiriyan,

This is similar to the case in multiple regression. The results are likely to be different when testing all predictors or one predictor at a time. In your case, only Individualism is statistically significant. You may focus on it.

Best,
Mike

> ## All moderators 
> anova(mx.fit1, mx.fit0)
             base   comparison ep  minus2LL df       AIC   diffLL diffdf          p
1 Ax as moderator         <NA> 18 -95.53248 42 -179.5325       NA     NA         NA
2 Ax as moderator No moderator  6 -73.93884 54 -181.9388 21.59365     12 0.04233461
> ## One moderator at a time
> anova(mx.fit1_Mean_Age, mx.fit0)
             base   comparison ep  minus2LL df       AIC    diffLL diffdf         p
1 Ax as moderator         <NA>  9 -74.75692 51 -176.7569        NA     NA        NA
2 Ax as moderator No moderator  6 -73.93884 54 -181.9388 0.8180842      3 0.8451368
> anova(mx.fit1_Individualism_Score_CON, mx.fit0)
             base   comparison ep  minus2LL df       AIC   diffLL diffdf         p
1 Ax as moderator         <NA>  9 -83.90478 51 -185.9048       NA     NA        NA
2 Ax as moderator No moderator  6 -73.93884 54 -181.9388 9.965939      3 0.0188579
> anova(mx.fit1_Female_Percentage, mx.fit0)
             base   comparison ep  minus2LL df       AIC   diffLL diffdf         p
1 Ax as moderator         <NA>  9 -76.67241 51 -178.6724       NA     NA        NA
2 Ax as moderator No moderator  6 -73.93884 54 -181.9388 2.733568      3 0.4345529
> anova(mx.fit1_Design, mx.fit0)
             base   comparison ep  minus2LL df       AIC   diffLL diffdf         p
1 Ax as moderator         <NA>  9 -78.74753 51 -180.7475       NA     NA        NA
2 Ax as moderator No moderator  6 -73.93884 54 -181.9388 4.808693      3 0.1863537
Dabiriyan's picture
Offline
Joined: 09/30/2019 - 07:42
Thanks!

Dear Mike,
Thank you very much for your reply. I really appreciate it.

ya's picture
ya
Offline
Joined: 11/28/2013 - 06:10
question on moderation

Dear Mike,

I have a fake dataset I made myself to try out the OSMASEM models. There are missing correlations and missing values in the moderator. My questions are:

  1. can OSMASEM handle missing values in moderator? the code with missing moderator values seems working, but how does the missing moderator values handled?

  2. I followed your OSMASEM moderation code in ' MASEM on Nohe et al. (2015) data Suzanne Jak and Mike Cheung June 17, 2020 '. For the moderation effect, you seem to have 4 lines of results corresponding to the 4 paths in the Ax, so I expect I will have 3 lines of results since I have 3 paths in the Ax. However, I got only one line of result with the name 'moderated':

> summary(osmasem2)
Summary of moderating all

free parameters:
name matrix row col Estimate Std.Error A z value Pr(>|z|)
1 medONx A0 med x -0.2116346 14.247970 -0.014853667 0.9881489
2 yONx A0 y x 0.8599042 5.358775 0.160466578 0.8725135
3 yONmed A0 y med 0.2461819 26.169723 0.009407127 0.9924943
4 xWITHx S0 x x 0.2009616 25.820149 0.007783129 0.9937900
5 moderated Ax1 2 1 0.1000000 NA ! NA NA
6 Tau1_1 vecTau1 1 1 -2.3411371 6.558308 -0.356972730 0.7211122
7 Tau1_2 vecTau1 2 1 -0.8892047 15.058792 -0.059048869 0.9529132
8 Tau1_3 vecTau1 3 1 -1.0218680 13.109379 -0.077949382 0.9378683

The name of the term and the number of the terms are both not correct.

I guess the fake data caused the NAs, but I am not sure about the ' moderated ' term. I am using OpenMx version number: 2.18.1, whereas you used OpenMx version number: 2.17.4 , does that matter?

Thank you very much.

File attachments: 
Mike Cheung's picture
Offline
Joined: 10/08/2009 - 22:37
Hi Ya,

Hi Ya,

1) OSMASEM treats the moderators as definition variables. Therefore, NA is not allowed in the moderators.
2) I have made some changes in your script. Please see the attached one.

Best,
Mike

File attachments: 
sharmel's picture
Offline
Joined: 07/31/2023 - 13:19
Subgroup/moderator analysis in metaSEM::wls()--two-stage MASEM

Dear Mike,

Is it possible to do subgroup/moderator analysis at the 2nd stage of MASEM using "wls()"?

Generally, is there an example, tutorial, or other resource to show how to do that in 2-stage metsSEM?

--Thank you

Mike Cheung's picture
Offline
Joined: 10/08/2009 - 22:37
You can convert models to

You can convert models to mxModel and conduct a multiple-group analysis, but calculating goodness-of-fit indices manually is necessary.

library(metaSEM)
 
## Sample sizes
n1 <- 100
n2 <- 200
 
## Variable labels
vars <- c("y", "x1", "x2")
 
## Group 1 data and model
R1 <- matrix(c(1.00, 0.22, 0.24, 
               0.22, 1.00, 0.30, 
               0.24, 0.30, 1.00), ncol=3, nrow=3,
             dimnames=list(vars, vars))
acov1 <- asyCov(R1, n1)
 
model1 <- "y ~ b1a*x1 + b2*x2
           ## Variances of x1 and x2 are 1
           x1 ~~ 1*x1
           x2 ~~ 1*x2
           ## x1 and x2 are correlated
           x1 ~~ r*x2"
 
RAM1 <- lavaan2RAM(model1, obs.variables=vars)
 
wls1 <- wls(model="Group1", Cov=R1, aCov=acov1, n=n1, RAM=RAM1, run=FALSE)
 
## Group 2 data and model
R2 <- matrix(c(1.00, 0.33, 0.41, 
               0.33, 1.00, 0.35, 
               0.41, 0.35, 1.00), ncol=3, nrow=3,
             dimnames=list(vars, vars))
acov2 <- asyCov(R2, n2)
 
model2 <- "y ~ b1b*x1 + b2*x2
           ## Variances of x1 and x2 are 1
           x1 ~~ 1*x1
           x2 ~~ 1*x2
           ## x1 and x2 are correlated
           x1 ~~ r*x2"
 
RAM2 <- lavaan2RAM(model2, obs.variables=vars)
 
wls2 <- wls(model="Group2", Cov=R2, aCov=acov2, n=n2, RAM=RAM2, run=FALSE)
 
## Combine both groups
wls.model <- mxModel(model="combined", wls1, wls2, mxFitFunctionMultigroup(c("Group1", "Group2")))
 
wls.fit <- mxRun(wls.model)
 
summary(wls.fit)
sharmel's picture
Offline
Joined: 07/31/2023 - 13:19
Thanks, so much. So, what you

Thanks, so much. So, what you demonstrated is essentially the extent users can perform moderator analysis in the context of two-stage MASEM, right?

Also, is there a way to compare b1a and b1b? (Also, is there a reason CIs are NA?)

Finally, can model1 and model2 be the same (but with different data) to compare how all loadings change across the two models?

Mike Cheung's picture
Offline
Joined: 10/08/2009 - 22:37
The metaSEM mainly uses the

The metaSEM mainly uses the OpenMx package to conduct meta-analyses. If you want to run analyses unavailable in metaSEM, you may need to use the OpenMx package.

It is a multiple-group SEM or a subgroup analysis in meta-analysis.

In the example, the created object "wls.model" is a MxModel object in OpenMx. You may perform standard analyses in OpenMx. For example,
1) Requesting CIs: mxRun(..., intervals=TRUE)
2) Comparing b1a and b1b: nested models comparison with a chi-square statistic.
3) Using the same model in model1 and model2: yes, you may replace model2 with model1.

sharmel's picture
Offline
Joined: 07/31/2023 - 13:19
Thanks so much.

Thanks so much.

sharmel's picture
Offline
Joined: 07/31/2023 - 13:19
Mike, is there a reason I can

Mike, is there a reason I can't see the path coefficient estimates for "Group2"?

library(metaSEM)
 
## Sample sizes
n1 <- 100
n2 <- 200
 
## Variable labels
vars <- c("y", "x1", "x2")
 
## Group 1 data and model
R1 <- matrix(c(1.00, 0.22, 0.24, 
               0.22, 1.00, 0.30, 
               0.24, 0.30, 1.00), ncol=3, nrow=3,
             dimnames=list(vars, vars))
acov1 <- asyCov(R1, n1)
 
model1 <- "y ~ x1 + x2
           ## Variances of x1 and x2 are 1
           x1 ~~ 1*x1
           x2 ~~ 1*x2
           ## x1 and x2 are correlated
           x1 ~~ x2"
 
## Group 2 data but model is the same as model1
R2 <- matrix(c(1.00, 0.33, 0.41, 
               0.33, 1.00, 0.35, 
               0.41, 0.35, 1.00), ncol=3, nrow=3,
             dimnames=list(vars, vars))
acov2 <- asyCov(R2, n2)
 
RAM1 <- lavaan2RAM(model1, obs.variables=vars)
 
wls1 <- wls(model="Group1", Cov=R1, aCov=acov1, n=n1, RAM=RAM1, run=F)
 
wls2 <- wls(model="Group2", Cov=R2, aCov=acov2, n=n2, RAM=RAM1, run=F)
 
## Combine both groups
wls.model <- mxModel(model="combined", wls1, wls2, mxFitFunctionMultigroup(c("Group1", "Group2")))
 
wls.fit <- mxRun(wls.model, intervals=TRUE)
 
zz = summary(wls.fit)
 
cbind(zz$parameters[-c(3:4,7:10)], zz$CI[c("lbound","ubound")])
 
      name         matrix  Estimate  Std.Error     lbound    ubound
1    yONx1 Group1.Amatrix 0.1986787 0.05468170 0.09107382 0.3064172
2    yONx2 Group1.Amatrix 0.2962857 0.05335658 0.19111701 0.4018717
3 x1WITHx2      Group1.S1 0.3303557 0.05114354 0.22974948 0.4305999
Mike Cheung's picture
Offline
Joined: 10/08/2009 - 22:37
The parameters are identical

The parameters are identical in both groups. Thus, only those in the first group are reported.

sharmel's picture
Offline
Joined: 07/31/2023 - 13:19
Thanks, I think you mean

Thanks, I think you mean something like below, if full models are to be compared for each group?

But is there any shortcut to avoid repeating the exact same models with different suffixes (e.g., b1a vs. b1b)? For example, a shortcut using lavaan2RAM(..., ngroups=2) etc.?

model1 <- "y ~ b1a*x1 + b2a*x2
           ## Variances of x1 and x2 are 1
           x1 ~~ 1*x1
           x2 ~~ 1*x2
           ## x1 and x2 are correlated
           x1 ~~ ra*x2"
 
model2 <- "y ~ b1b*x1 + b2b*x2
           ## Variances of x1 and x2 are 1
           x1 ~~ 1*x1
           x2 ~~ 1*x2
           ## x1 and x2 are correlated
           x1 ~~ rb*x2"
sharmel's picture
Offline
Joined: 07/31/2023 - 13:19
MetaSEM: Warning Message "free dependent variables variances"

Dear Mike,

I was wondering why I'm getting a warning in wls() saying: The variances of the dependent variables in 'Smatrix' should be free.?

If this is a harmful warning, how can I remove it?

library(metaSEM)
Cov = structure(c(1, 0.55, 0.5, 0.36, 0.57, 0.47, 0.55, 0.44, 0.55, 
                  1, 0.36, 0.21, 0.39, 0.26, 0.42, 0.3, 0.5, 0.36, 1, 0.52, 0.56, 
                  0.37, 0.54, 0.55, 0.36, 0.21, 0.52, 1, 0.53, 0.34, 0.64, 0.59, 
                  0.57, 0.39, 0.56, 0.53, 1, 0.43, 0.5, 0.53, 0.47, 0.26, 0.37, 
                  0.34, 0.43, 1, 0.41, 0.34, 0.55, 0.42, 0.54, 0.64, 0.5, 0.41, 
                  1, 0.52, 0.44, 0.3, 0.55, 0.59, 0.53, 0.34, 0.52, 1), dim = c(8L,8L),
                dimnames = list(c("L2DA", "L2DF", "L2G", "L2L", "L2M", "L2P", 
                                  "L2R", "L2V"), c("L2DA", "L2DF", "L2G", "L2L", "L2M", "L2P", 
                                                   "L2R", "L2V"'Comprehension =~ L2L + L2V + L2G
 
   Decoding =~ L2DA + L2DF
 
   Meta =~ L2P + L2M
 
   L2R ~ Comprehension + Decoding
 
   Comprehension ~~ Meta
 
   Decoding ~ Meta
 
   Comprehension ~~ Decoding'
 
RAM <- lavaan2RAM(ModelA, colnames(Cov))
 
wls(Cov=Cov, aCov=aCov, n=333, RAM=RAM)
 # Warning: The variances of the dependent variables in 'Smatrix' should be free.
Mike Cheung's picture
Offline
Joined: 10/08/2009 - 22:37
"Decording" regresses on

"Decording" regresses on "Meta." If this is what you want, you may ignore the warning.

sharmel's picture
Offline
Joined: 07/31/2023 - 13:19
Thanks, Mike. Can you please

Thanks, Mike. Can you please clarify, why you "Decording" being regressed on "Meta" generates that warning?

Mike Cheung's picture
Offline
Joined: 10/08/2009 - 22:37
The checkRAM() function

The checkRAM() function triggers the warning, which runs a few basic checks on the RAM model. Specifically, the issue is related to the "Decoding" variable, which is a dependent variable, and its error variance should be assumed free. The checkRAM() function has identified this issue, but the wls() function is smart enough to handle it. Therefore, you may safely ignore the warning if this is your intended model.

sharmel's picture
Offline
Joined: 07/31/2023 - 13:19
Thanks so much, Mike. Just

Thanks so much, Mike. Just curious, how could I let the error variance for "Decoding" (dependent variable) to be free in the model syntax? Should I add 'Decoding ~~ Decoding'?

Mike Cheung's picture
Offline
Joined: 10/08/2009 - 22:37
The metaSEM package uses the

The metaSEM package uses the function lavaan2RAM(), which internally calls the lavaan::lavaanify() function, to convert the lavaan model to RAM specification. If you need to release the error variance of "Decoding," you can use the following code. If you are curious about why this step is necessary, please check the help manual of lavaan::lavaanify().

ModelB <-
  'Comprehension =~ L2L + L2V + L2G
   Decoding =~ L2DA + L2DF
   Meta =~ L2P + L2M
   L2R ~ Comprehension + Decoding
 
   Comprehension ~~ Meta
   Decoding ~ Meta
   Comprehension ~~ Decoding
 
   Comprehension ~~ 1*Comprehension
   Meta ~~ 1*Meta
   '
RAM2 <- lavaan2RAM(ModelB, colnames(Cov), std.lv=FALSE)
fit2 <- wls(Cov=Cov, aCov=aCov, n=333, RAM=RAM2)
sharmel's picture
Offline
Joined: 07/31/2023 - 13:19
Mike, thanks, it seems that

Mike, thanks, it seems that you also set std.lv=FALSE, which by default is std.lv=TRUE. Although, the bottom line is that these warnings won't have any impact on the output as wls() will let the error variances of the dep. variable be free.