# one-factor CFA, 4 indicators, correlation matrix

10 posts / 0 new
Offline
Joined: 12/29/2009 - 17:45
one-factor CFA, 4 indicators, correlation matrix

Hello! As the subject line states, I want to run a one-factor CFA with four indicators; however, when I run the model in OpenMx, I get -2 degrees of freedom. That makes sense because there are 6 correlations (given 4 indicators), and if I fix the factor variance to 1.0, I have to estimate 4 loadings and 4 error variances = 8 estimates, and we all know that 6 correlations - 8 estimates = -2 df.

However, we can constrain the estimation such that lambda-squared + error variance = 1.0 for each variable - how do I do this (I thought it would be automatic by virtue of using correlation, but probably a good thing that it is not)? Thanks! Fred

Offline
Joined: 07/31/2009 - 15:12
You seem to be using a

You seem to be using a correlation matrix as input. I strongly encourage you not to do so. Cudeck (1989; Psych Bulletin) gives some of the problems associated with this technique, and I'll add that there's no reason to throw away information about variances. In some models (growth curve in particular), analysis of correlation matrices rather than covariance matrices will give you decidedly incorrect answers. The forums already contain a function for standardizing RAM models; that thread should also give instructions for standardizing arbitrary models.

That said, constraining variances to 1 is relatively straightforward, and has global applications beyond your problem. You can use mxConstraints if you wish, but I'll recommend another technique. If you were specifying residuals as a matrix, then you can instead define your residual matrix as an identity matrix minus the squared loadings. If your loading matrix is 4 x 1, then use this:

mxMatrix("YourModel",
...
mxMatrix("Iden", 4, 4, name="I"),
...
)

First, I'll make an identity matrix, which provides the 1s for the variances to sum to. Then I subtract the squared loadings. I'll square with kronecker exponentiation (%^%, which just becomes elementwise exponentiation when the second argument is a scalar like 2). That leaves me with a 4 x 1 matrix of squared loadings; using the vec2diag function turns that column of squared loadings into a matrix with those squared loadings on the diagonal and zeros elsewhere). When I subtract that new matrix from the identity matrix, I'm left with a diagonal matrix with my constrained residual variance terms on the diagional. Use that algebra the same way you would use a residual matrix.

If you're using paths instead of matrices, I again strongly strongly urge you to use the standardizeRAM function and to analyze covariances rather than a correlation matrix. 
Offline
Joined: 12/29/2009 - 17:45
Ryan - This is extremely

Ryan - This is extremely helpful - thank you so much for your time and thought in answering. I actually had the chance to work with Cudeck a bit as a grad student at U Minnesota (great guy!). For the purposes of this one-factor CFA exercise, I'm willing to live with the information lost through standardizing and realize (from Cudeck) the perils in doing so. Thanks again - I'm guessing I'll have a few more questions down the road, but so far I am very excited about OpenMx and the supportive community of people like yourself. Take care - Fred

Offline
Joined: 12/29/2009 - 17:45
Ryan - Again, thanks for your

Ryan - Again, thanks for your help. See the attached program file, a modified version of your matrix-based one-factor CFA based on a covariance matrix.

I attempted to incorporate the restriction that residual = 1-loadings^2, but can't get things to mesh: e.g., (1) Matrices S and A have the last row and column that is 'extra' in that it pertains to the latent factor. I assume I cannot just say mxAlgebra(I-(S%x%2), name="residuals")...or can I? (2) Is the specification in mxAlgebra a constraint that gets passed into the MxObjective function?

Being so new to OpenMx, making direct suggestions based on the attached program might be quicker than figuring out my questions. Thanks! Fred

Offline
Joined: 12/29/2009 - 17:45
appreciate any thoughts on

appreciate any thoughts on the previous comment and file - thanks y'all! - Fred

Offline
Joined: 07/31/2009 - 15:12
Here are two versions. In the

Here are two versions. In the first, I'll take the provided RAM specification and add mxAlgebra statements to make the constraints listed above. Instead of creating a submatrix of A to make the constraint I described above, I made one mxAlgebra constraint per factor loading and used square-bracket substitution to make the constraint. This relies on two fun OpenMx features:
1.) free parameters can be treated as 1 x 1 matrices in algebra expressions. The free parameter "l1" can be treated as though it is its own matrix even though it's an element in the A matrix.
2.) labels can be used to populate values from one matrix to another. In the attached code, I constrain the residual variance for item 1 to be equal to the first row and first column of the result of mxAlgebra "e1". That algebra expression defines the residual variance for the first variable as 1 - loading squared, so the only element (by definition, the [1,1] element) is the residual variance.

This spec adds six lines to the code you provided because there are six variables. If you had 100 variables, this solution would not be tenable. I also provided a more LISREL-like specification of the exact same model, which allows for a more parsimonious specification of the constraints.

These two methods are only a few of the many, many ways you could make this constraint (which again could be avoided by using covariance data rather than the information-losing bias-inducing correlation matrix). Explore the program and decide which method makes the most sense for your particular model.

-ryne

Offline
Joined: 12/29/2009 - 17:45
Once again, amazingly helpful

Once again, amazingly helpful - thank you, and I am guessing that more questions will arise as I attempt to convert myself and my CFA/SEM students this semester to OpenMx users. I sincerely appreciate your help! - Fred

Offline
Joined: 12/29/2009 - 17:45
Ryne - Sorry to have

Ryne - Sorry to have misspelled your name repeatedly in previous e-mails! I could not get the first model in the modified code to run (one comma was missing, but the error remained) - any additional help appreciated, just so I can see how working versions operate in both RAM and LISREL-like notation. Thanks again - Fred

Offline
Joined: 07/31/2009 - 15:12
Ah, two problems. I forgot a

Ah, two problems. I forgot a comma after the free=FALSE statement in the S matrix. Once I fixed that, I had to change the starting values so that the expected correlation matrix at the first occasion wasn't all 1s. This should work.

ryne

Offline
Joined: 12/29/2009 - 17:45
Indeed - thanks again, Ryne!

Indeed - thanks again, Ryne! Truly appreciate all your help - take care - Fred