You are here

Constrain correlation matrices

9 posts / 0 new
Last post
GRBS's picture
Offline
Joined: 02/13/2015 - 12:56
Constrain correlation matrices

I have fit two saturated models and have created correlation matrices from the expected covariance matrices using the cov2cor function. I would like to constrain the correlation matrices to equality between these models without constraining the covariance matrices.

I have tried adding a mxConstraint object to the combined model but I get errors and I am not able to constrain them by equating labels, as far as I can figure out. I'm just wondering if anyone has done anything like this? I'm sure I'm missing something very simple - I am brand new to all of this so the learning curve is a little steep at the moment.

Thanks!
Gretchen

RobK's picture
Offline
Joined: 04/19/2011 - 21:00
Correlations and SDs

Try parameterizing the covariance matrices in terms of correlations and standard deviations. Your two models would have the same correlation matrix, but different SDs. The labels for the correlations would be the same for both models, but the labels for the SDs would be different.

For example, suppose R is the correlation matrix, and D is a diagonal matrix that has the model's SDs on its diagonal. Then, the MxAlgebra D %*% R %*% D would give you the model's covariance matrix. Alternately, suppose R is the correlation matrix as before, and s is a column vector containing the model's SDs. Then, the MxAlgebra R * (s%*%t(s)) would also give you the model's covariance matrix.

Obviously, this approach doesn't produce a covariance matrix from the product of Cholesky factors, so the resulting covariance matrix could become non-positive-definite during optimization. It's therefore especially important to pick good start values.

Does this help? I could be more specific if you posted some of your script.

GRBS's picture
Offline
Joined: 02/13/2015 - 12:56
Hey Rob! I hear a lot about

Hey Rob! I hear a lot about you from Matt and Bridget. Thank you so much for your help!

I think I understand and have incorporated what you said. I am pretty sure I am now having trouble with the start values as you predicted. Do you have any words of wisdom about these?

I have attached my script in the hopes that it helps.

Thanks!
Gretchen

RobK's picture
Offline
Joined: 04/19/2011 - 21:00
Correlation matrix should be of type "Stand"

The correlation matrix (since I'm not sure you need two) should be of type "Stand" (i.e., standardized), not "Symm" (i.e., merely symmetric). As it is now, your script is allowing the diagonal elements of the correlation matrices to be free parameters, but they must be fixed at 1.

First, define cor_label differently:

cor_label    <- matrix(
  c("r11","r21","r31","r41","r51","r61","r71",
    "r21","r22","r32","r42","r52","r62","r72",
    "r31","r32","r33","r43","r53","r63","r73",
    "r41","r42","r43","r44","r54","r64","r74",
    "r51","r52","r53","r54","r55","r65","r75",
    "r61","r62","r63","r64","r65","r66","r76",
    "r71","r72","r73","r74","r75","r76","r77"),
  nrow=7,ncol=7)

Now, define the correlation matrix as:

R <- mxMatrix("Stand", nv, nv, T, 0,
               labels=cor_label[lower.tri(cor_label,diag=F)], 
               name="R" )

Like I said, I think you probably only need one correlation matrix, which you can just use in both the males' and females' models. You want to set up a model in which the correlations are the same for males and females, right?

When you set up the supermodel that will contain the models for the males and females, define it like this:

eqCor_gender <- mxModel( model_m, model_f, 
                         mxFitFunctionMultigroup(c("males.fitfunction","females.fitfunction")),
                         name="eqCor_gender")

If you take a look at the start values for the correlations, with R$values, you'll see that they're all zero. You might want to change them to something more reasonable--something closer to what you think their estimate will be. You could do that by providing start values via the values argument to mxMatrix() when you create R, or by altering the 'values' matrix directly (e.g., R$values[1,2] <- 0.5) before you put R into a model, or by using omxSetParameters() on eqCor_gender once it's been created.

GRBS's picture
Offline
Joined: 02/13/2015 - 12:56
Thank you. I do only need one

Thank you. I do only need one correlation matrix because I want to be the same - not sure why I thought two were necessary at all. And I see how you set the diagonals of R to be fixed - I didn't realize how that was done, so that is immensely helpful.

Hopefully this is my last question, but when I try to run the combined model with the mxFitFunctionMultigroup added in, I get this error:

Running eqCor_gender
Error: eqCor_gender.fitfunction: cannot locate algebra/fitfunction 'males.fitfunction'

I feel like I have tried everything to figure out what this means/what is missing. Do you have any ideas what I might be doing wrong?

I've attached my updated script again. Thank you again for your help!

RobK's picture
Offline
Joined: 04/19/2011 - 21:00
Order of arguments to mxModel()

Ah, OK, I think we're both getting tripped up on the order of arguments supplied to mxModel(). Try this instead:

eqCor_gender   <- mxModel("eqCor_gender",
                          model_m, model_f, 
                          mxFitFunctionMultigroup(c("males.fitfunction","females.fitfunction")))

The first argument to mxModel() is model, which can either be a character string or an MxModel object. If it's a string, the function creates a new MxModel object with name equal to the string. If it's an MxModel object, the function pulls all of that object's contents into the MxModel object it returns. So, what I think was happening with your syntax was that mxModel() was returning a model that contained all of the contents of model_m, plus model_f itself as a submodel. Note that it did not contain model_m as a submodel, so there was nothing called "males.fitfunction" in its namespace.

So basically, don't provide an MxModel object as argument model unless you want to get that same MxModel back, with additional stuff possibly added to it.

tbates's picture
Offline
Joined: 07/31/2009 - 14:25
mxFitFunctionMultigroup(c("model1", "model2"))

I think the mxFitFunctionMultigroup() just wants a list of model names, so

mxFitFunctionMultigroup((c("males", "females"))
#instead of
mxFitFunctionMultigroup((c("males.fitfunction", "females.fitfunction"))
jpritikin's picture
Offline
Joined: 05/24/2012 - 00:35
mxFitFunctionMultigroup

There was a bug recently fixed in trunk. If you are using 2.0.1 then you should use "model.fitfunction" to avoid problems.

GRBS's picture
Offline
Joined: 02/13/2015 - 12:56
Ah, totally understand now. I

Ah, totally understand now. I hadn't considered the order of the arguments that I had put in.

Thank you again for all of your help! Very much appreciated!