Basic questions on CFA and OpenMx

10 replies [Last post]
AnneN.'s picture
Offline
Joined: 02/27/2014

Hi all,
I am VERY new to SEM and also to OpenMx and I am trying to run a very simple CFA in OpenMx, which has 1 latent factor (F1) and 3 indicators of A, B, and C with C as my scaling variable and I have a couple of questions about the output that I got:
(1) The output provides information on "Estimate", "Std. Error", "Std. Estimate", "Std. SE" and my question is: how do I derive the Std. Estimate based on the other info in the output that I got? For example, from indicator A to F1, Estimate is .6987, Std. Error is: .1245, Std. estimate is .6571, and Std. SE is .11715045. So let's say that the output didn't provide the Std. estimate. How do I obtain .6571 based on the other results?

(2) I compared the answers from OpenMx to the answers I got from Amos, and I got all identical results as far as standardized path loadings. However, in Amos, it gives me the standardized estimate for the path between C and F1, but in OpenMx, it only gives me standardized path coefficients for A to F1, and B to F1. Therefore, in my script, how do I get to specify that C is my scaling indicator and still allow OpenMx to estimate its standardized path loading just like in Amos?

Thank you so much in advance for your help on this, and please let me know if I need to clarify anything.
Sincerely,
Anne

RobK's picture
Offline
Joined: 04/19/2011
Hello, AnneN. Welcome to SEM

Hello, AnneN. Welcome to SEM and OpenMx.

I'll assume from your post that you're doing a RAM model, and that the factor loading for your variable 'C' is fixed to 1.

In summary() output, the column labeled 'Std. Estimate' contains estimates of the standardized path coefficients. Unstandardized ("raw") path coefficients on single-headed arrows are regression coefficients, thus, standardized path coefficients on single-headed arrows are standardized regression coefficients or "beta weights." Unstandardized path coefficients on double-headed arrows that go from a variable to itself are variances or variance components (such as residual variance); the corresponding standardized coefficients are variance proportions. Unstandardized path coefficients on double headed arrows that connect two different variables are covariances, thus, when standardized, they're correlations.

To turn a raw path coefficient into a standardized one, you'd need to know the full variance of the variables it connects, and it would be tedious to work that out from the summary() output alone. But it's pretty easy to include a few mxAlgebra objects in your mxModel that compute it for you.

I'll try to keep the explanation of how to do that as simple as I can. Let's assume your mxModel object is called myModel and you ran the line

myFit <- mxRun(myModel)

Make sure that all of your model's two-headed paths have non-zero start values; if necessary, add values=0.1 to the mxPath objects that don't have such a values statement. Now, make a new mxModel and run it as follows:
myModelZ <- mxModel(model=myModel,
     mxMatrix(type="Iden",nrow=nrow(myModel$A@values),name="I"),
     mxAlgebra( vec2diag(diag2vec( solve(I-A)%*%S%*%t(solve(I-A)) )%^%-0.5) ,
                                   name="InvSD"),
                        mxAlgebra( InvSD %*% A %*% solve(InvSD),
                                  name="Az",dimnames=dimnames(myModel$A@values)),
                        mxAlgebra( InvSD %*% S %*% InvSD, 
                                  name="Sz",dimnames=dimnames(myModel$S@values))
)
myFitZ <- mxRun(myModelZ)

You can then query the values of ALL the standardized path coefficients with:
myFitZ$Az@values #Standardized path coefficients for single-headed arrows
myFitZ$Sz@values #Standardized path coefficients for double-headed arrows

You'll be able to match standardized values to their unstandardized counterparts by looking at the names of the row and column containing each, and comparing to the 'row' and 'column' columns of the 'free parameters' table in summary() output.

So far, what I've described will give you all the standardized point estimates. If you want interval estimates to go along with them, here is what you would do instead:

myModelZ <- mxModel(model=myModel,
     mxMatrix(type="Iden",nrow=nrow(myModel$A@values),name="I"),
     mxAlgebra( vec2diag(diag2vec( solve(I-A)%*%S%*%t(solve(I-A)) )%^%-0.5) ,
                                   name="InvSD"),
                        mxAlgebra( InvSD %*% A %*% solve(InvSD),
                                  name="Az",dimnames=dimnames(myModel$A@values)),
                        mxAlgebra( InvSD %*% S %*% InvSD, 
                                  name="Sz",dimnames=dimnames(myModel$S@values)),
     mxCI(c("Az","Sz"))
)
myFitZ <- mxRun(myModelZ,intervals=T)
summary(myFitZ)

The summary() output will contain each point value and the upper and lower confidence limits.

AnneN.'s picture
Offline
Joined: 02/27/2014
Hi Rob and mhunter, Many

Hi Rob and mhunter,
Many sincere thanks for taking the time to help me with my problem. If you don't mind, I have several follow up questions regarding your suggestions:
(1) When I added the scripts suggested by Rob to my RAM model, and then queried all standardized path coefficients with "myFitZ$Az@values", I got an error that says "Error: no slot of name "values" for this object of class "MxAlgebra." I did spend sometime searching on the internet to figure out why this may be, but I still don't know what I need to do to the model in order for this statement to work. In order to make things more concrete, I attached my script here. In this RAM model, I am doing a phenotypic cholesky, or a hierarchical regression using latent traits. My first order latent factors are: Word, Vocab, and Comp and my second order latent factors are: F1, F2, and F3. F1 goes to all 3 latent variables, F2 goes to the remaining 2 latent variables, and F3 goes to the remaining latent variable. The output that I got, once again, gave me the standardized estimates for the parameters that I estimated. But I would like to get the model to give me the standardized path estimates for the fixed ones as well, e.g., "b" and Word, "d" and Vocab, and "g" to Com.
(2) Rob, could you explain conceptually what those mxAlgebra objects contain and how do they help me obtain the standardized path coefficients? Or if you could point me to a source that explains the rationale behind these statements, I would really appreciate it.
(3) And thank you mhunter for clarifying that Amos doesn't really estimate the paths that are fixed to 1. This makes so much sense.

Thank you, and I look forward to hearing your insights on this,
Anne

AttachmentSize
Phenotypic Choleskys_to sumbit to OpenMx Forum.R 3.73 KB
tbates's picture
Offline
Joined: 07/31/2009
m1$Az@result

algebras have a "result" rather than "values", so I think

m1$Az@values

should be

m1$Az@result

RobK's picture
Offline
Joined: 04/19/2011
My mistake!

Oops! Yes, Tim Bates is correct--use "result" rather than "values" for an algebra, or as Hunter says, just use mxEval() all the time.

Sorry for the confusion, Anne. I'm rather chagrined because I DO know better than to make this mistake.

AnneN.'s picture
Offline
Joined: 02/27/2014
Hi Rob, Many thanks again for

Hi Rob,
Many thanks again for your help before and don't worry. As a matter of fact, I am so glad that this happened because now, I am aware of the difference between result vs. values and what to do the next time something like this happens again.
Sincerely,
Anne

mhunter's picture
Online
Joined: 07/31/2009
mxEval

This confusion is precisely why we recommend that you always use mxEval.

mxEval(YourAlgebraOrMatrix, YourModel)

Algebras do not have values, they have a result; matrices have values, not a result. This is confusing and hard to remember. The function mxEval gives you the values of a matrix or the result of an algebra, whichever is needed. So, there's only one function you need to remember: mxEval. Here's a use case relevant for you,

mxEval(Az, m1)

You may need to recompute it if you have not yet run the model.

mxEval(Az, m1, compute=TRUE)

AnneN.'s picture
Offline
Joined: 02/27/2014
mhunter, I just tried the

mhunter,
I just tried the mxEval and this worked wonderfully! I will keep in mind your warnings about the differences between algebras and matrices and I agree that it's probably best for me to stick to mxEval.
Gratefully,
Anne

AnneN.'s picture
Offline
Joined: 02/27/2014
Yes, tbates! You are right.

Yes, tbates! You are right. When I tried with "result" rather than "values", it worked! Thank you so much for your help!
Anne

RobK's picture
Offline
Joined: 04/19/2011
OpenMx 2.0

BTW, OpenMx 2.0 has a new function, mxStandardizeRAMpaths(), that provides a table of standardized values for ALL nonzero path coefficients.

mhunter's picture
Online
Joined: 07/31/2009
To answer your second

To answer your second question, neither Amos nor OpenMx is estimating the standardized path coefficient between C and F1. In fact, standardized path coefficients aren't estimated at all. They are calculated based on the estimated path coefficients. You are observing that Amos reports the standardized value of a parameter that is not estimated, whereas OpenMx only reports the standardized values of free parameters. Because the path between C and F1 is not free, we do not currently report a standardized value for it in summary(). The summary() only reports on free parameters.

Rob's code will give you the standardized values of all your parameters, regardless of them being fixed or free.