# multilevel path/structural equation models in OpenMx

18 posts / 0 new
Offline
Joined: 05/08/2017 - 11:45
multilevel path/structural equation models in OpenMx
AttachmentSize
1.26 MB
158.41 KB

Hi,

Is it possible to estimate multilevel path/structural equation models with OpenMx?
If it is possible, is there an example code for multilevel mediation (path) model?

Attached files are the example of multilevel path model using Mplus.
Source: Heck, R. H., & Thomas, S. L. (2015). An introduction to multilevel modeling techniques: MLM and SEM approaches using Mplus. Routledge.

Hope I can do the same analysis using OpenMx.

Soyoung.

Offline
Joined: 03/01/2013 - 11:03
Yep

It is possible to estimate multilevel structural equations in OpenMx. This paper by Pritikin et al. discusses many of the details and provides some example scripts.

Many-Level Multilevel Structural Equation Modeling: An Efficient Evaluation Strategy

Offline
Joined: 12/12/2012 - 12:15
voila

Here's a similar model (see attachment). You probably need to add/remove a few paths to make it identical to what you posted. I find it tedious to read Mplus model diagrams or tables.

File attachments:
Offline
Joined: 05/08/2017 - 11:45
fabulous

Thank you all.

Two more questions.

[1]
I revised the code, and i though I made the same model.
BUT I found these results are not identical in terms of estimates.
Why did these have different results?
Which Estimation method the OpenMx use?
Mplus uses Robust-ML.

[2]
I want to estimate indirect effects in Multilevel SEM.
How can I set a product term (indirect effect parameter) in OpenMx?

File attachments:
Offline
Joined: 12/12/2012 - 12:15
questions
1. See imxRobustSE

2. Create an mxAlgebra and use mxCI or mxSE to request confidence intervals on it. See attached code.

File attachments:
Offline
Joined: 05/08/2017 - 11:45
Thank you

Thank you so much for your kind response.

All the best,
Soyoung.

Offline
Joined: 03/01/2013 - 14:09
Agreement

Hi Soyoung

Could you confirm that you were able to get the same estimates and goodness-of-fit statistics with the multilevel model in OpenMx when compared to Mplus?

Thanks
Mike

Offline
Joined: 05/08/2017 - 11:45
could not get the identical results

Hi, Mike.
I still could not get the identical results.
I am curious why these are different.

First, in terms of model fit statistics, two results were almost same.

 Mplus OpenMx RMSEA 0 0 CFI 1 NA TLI 1.001 1

BUT I don't think this example is suitable here, because these fit values are too perfect. It should be tested in the other data.

Second, in terms of estimates, I could not get the same estimates.
I'm trying to figure out why there are different results.

File attachments:
Offline
Joined: 01/24/2014 - 12:15
imxRobustSE()

I am pretty sure that imxRobustSE() does not correctly handle multilevel data; the matter of whether or not it does is currently a matter of disagreement among the OpenMx development team. I suggest you not rely too much on the robust SEs you get out of OpenMx.

Soyoung, could you post the OpenMx script you're currently working from?

Offline
Joined: 05/08/2017 - 11:45
sure

Hi Rob

Following code is based on what Dr.Pritikin provided.
You can find the data in post #1 .

library(OpenMx)
colnames(flatData) <- c("orgid",'female','white',
'satpay','morale','org1','org2','benefit','cond',
'resour','zproduct','lev1wt','lev2wt')

level1 <- flatData[,c('benefit','cond','female','white','orgid')]
level2 <- flatData[!duplicated(flatData\$orgid),c('orgid', 'org1','org2','zproduct')]

orgModel <- mxModel(
"org", type="RAM",
mxData(level2, 'raw', primaryKey = "orgid"),
manifestVars = c('zproduct'),
latentVars = c('Benefits','Conditions', 'org1','org2'),
mxPath(c('zproduct','Benefits','Conditions'), arrows=2, values=1),
mxPath('Benefits','Conditions', arrows=2),
mxPath('one', 'org1', labels='data.org1', free=FALSE),
mxPath('one', 'org2', labels='data.org2', free=FALSE),
mxPath('org1', c('Benefits', 'Conditions')),
mxPath('org2', 'zproduct', labels="a"),
mxPath('one', 'zproduct'),
mxPath('zproduct', c('Benefits','Conditions'), labels=paste0('b',1:2)),
mxMatrix(nrow=2, ncol=1, free=TRUE, labels=paste0('b',1:2), name='B'),
mxAlgebra(B * a, name="indirect")
)

empModel <- mxModel(
"emp", type="RAM", orgModel,
mxData(level1, 'raw'),
manifestVars = c('benefit','cond'),
latentVars = c('female','white'),
mxPath('one','female', labels='data.female', free=FALSE),
mxPath('one','white', labels='data.white', free=FALSE),
mxPath(c('female','white'), c('benefit','cond'), connect = "all.bivariate"),
mxPath(c('benefit','cond'), arrows=2, connect = "unique.pairs", values=c(1,0,1)),
mxPath('org.Benefits', 'benefit', values=1, free=FALSE, joinKey = "orgid"),
mxPath('org.Conditions', 'cond', values=1, free=FALSE, joinKey = "orgid"),
mxPath('one', c('benefit','cond')),
mxCI("org.indirect")
)

ch4M3 <- mxRun(empModel, intervals=TRUE)
summary(ch4M3)
imxRobustSE(ch4M3)
Offline
Joined: 01/24/2014 - 12:15
Under x86_64 Linux/GNU, I

Under x86_64 Linux/GNU, I substantively reproduce the OpenMx results you report with all 3 gradient-descent optimizers (script and output are attached).

Could you post the full output from MPlus? In particular, I'm curious if the -2logL matches.

File attachments:
Offline
Joined: 05/08/2017 - 11:45
full output

Yes. Attachment is full output.

Mplus reports LL -40521.828.
(-2) * (-40521.828) = 81043.656

Thank you.
Soyoung.

File attachments:
Offline
Joined: 03/01/2013 - 14:09
ML vs MLR?

Hi Soyoung, I notice that the estimator in MPlus is MLR, whereas in OpenMx it is FIML. Could you try it with ML (FIML) in Mplus to see if that changes the results?

Cheers
Mike

Offline
Joined: 05/08/2017 - 11:45
different

Hi Mike.
Attachment is the result of FIML,
but this is almost same as the result of MLR of Mplus,
and the estimates does not match the result of OpenMx.

I wonder why the two results are different...Where does the difference come from?
Is there a way to check local-maxima in OpenMx, by any chance?

Thank you.
Soyoung.

File attachments:
Online
Joined: 05/24/2012 - 00:35
fit value

One way to debug this is to load the parameter vectors into the OpenMx model using omxSetParameters and then evaluate the fit at that point using mxRun(mxModel(model, mxComputeOnce('fitfunction','fit'))). If the Mplus fit matches at a specific parameter vector then the models are likely the same. If the fit doesn't match then the models are different.

Offline
Joined: 01/24/2014 - 12:15
One way to debug this is to load the parameter vectors into the OpenMx model using omxSetParameters and then evaluate the fit at that point using mxRun(mxModel(model, mxComputeOnce('fitfunction','fit'))).

I already tried that (see my post, presently #17, below). The fit values don't match.

Online
Joined: 05/24/2012 - 00:35
robust

Good point Rob. I am not sure what Robust-ML means for multilevel models.

Offline
Joined: 01/24/2014 - 12:15
It appears that imxRobustSE()

It appears that imxRobustSE() does not calculate robust SEs in a manner theoretically correct for multilevel data (e.g., Freedman 2006).

It also appears that what OpenMx and MPlus are doing in this case are different enough that their results shouldn't be compared to each other. See the attached script and output. When OpenMx calculates the fit at MPlus' solution, OpenMx returns a different fit from MPlus. Further, I can start OpenMx at MPlus' solution, and OpenMx still returns the same solution it has before (with a fit value of 82001.55).

I don't know OpenMx's multilevel feature very well, and I don't know MPlus at all, so I'm not sure what might explain the difference (or even if Soyoung's syntax is even fitting equivalent models in the two software packages). Perhaps a difference in how the two programs internally handle zero-variance exogenous regressors? Does MPlus drop normalizing constants from its loglikelihood?

File attachments: