Cross-Lagged Model

12 replies [Last post]
ebejer's picture
Offline
Joined: 03/18/2010

Hi,

I have been trying to specify the parameters and constraints for a cross-lagged model, though I'm not sure how to identify it correctly (sorry if I use incorrect terminology). Some of the values are similar to what I would expect, though I'm thinking about how the data should behave given free or fixed parameters. I won't say anymore, rather I'll past the model below.

Any suggestions about how to set the parameters to get the most accurate estimate of what is going on in the data would be greatly appreciated. On another note when I post a message I receive this error message

'warning: implode(): Invalid arguments passed in /private/var/openmx/drupal-6.16/sites/all/modules/mollom/mollom.module on line 1439'

regards,
j

CrossLaggedModel<-mxModel("cross lagged correlation",
type="RAM",
manifestVars=c("f1A","f1B","f2A","f2B","f3A","f3B"),
latentVars="one",
mxData(observed=myCrossData, type="raw"),
mxPath(from="f1A", to="f2B", arrows=1, free=FALSE, values=.5),
mxPath(from="f1B", to="f2A", arrows=1, free=TRUE, values=.7),
mxPath(from="f1B", to="f1A", arrows=2, free=TRUE, values=.5),
mxPath(from="f1B", to="f2B", arrows=1, free=TRUE, values=.5),
mxPath(from="f1A", to="f2A", arrows=1, free=TRUE, values=.5),
mxPath(from="f2B", to="f3A", arrows=1, free=TRUE, values=.5),
mxPath(from="f2A", to="f3B", arrows=1, free=TRUE, values=.7),
mxPath(from="f2B", to="f2A", arrows=2, free=TRUE, values=.7),
mxPath(from="f2B", to="f3B", arrows=1, free=TRUE, values=.5),
mxPath(from="f2A", to="f3A", arrows=1, free=TRUE, values=.5),
mxPath(from="f3A", to="f3B", arrows=2, free=TRUE, values=.5),
mxPath(from=c("f1A","f1B","f2A","f2B","f3A","f3B"), arrows=2, free=c(F,F,T,T,T,T),
values=1, labels=c ("var1A","var1B","residualA","residualB","residualA","residualB")),
mxPath(from="one",
to=c("f1A","f1B","f2A","f2B","f3A","f3B"),
free=c(T,T,T,T,T,T), values=c(0,0,0,0,0,0), labels=c ("m1A","m1B","m2A","m2B","m3A","m3B"))
)

crossLaggedFit<-mxRun(CrossLaggedModel)

Ryne's picture
Offline
Joined: 07/31/2009
First, a few minor notes. You

First, a few minor notes. You don't have to specify "one" as a latent variable. OpenMx uses "one" as a reserved word to refer to "the constant", which is included to allow the specification of means. This constant represents a variable on which every individual is assigned a score of 1, which allows for the inclusion of intercepts and means in extensions of the general linear model. Second, when specifying a bunch of paths with a single mxPath statement, you can represent any value that is constant across all paths with a single value. This means that your statement:

mxPath(from="one",
to=c("f1A","f1B","f2A","f2B","f3A","f3B"),
free=c(T,T,T,T,T,T), values=c(0,0,0,0,0,0), 
labels=c ("m1A","m1B","m2A","m2B","m3A","m3B"))

can be shortened to

mxPath(from="one",
to=c("f1A","f1B","f2A","f2B","f3A","f3B"),
free=T, values=0, labels=c("m1A","m1B","m2A","m2B","m3A","m3B"))

which is easier to type. Third, try to post attachments (.R or .txt) instead of pasting code into the forums. Browsers tend to add a bunch of extra formatting to text to make it pretty, which can lead to problems when copied and pasted into R.

On to your problem. Your model contains all manifest variables, so there's no need for the variance restriction on the first occasion to "scale" the factor. I don't see any other problems with your model, but you need to clarify what you're testing. Most people generally constrain the same relationship to be the same over time, such that the one headed F1A->F2A path has the same value and label as F2A->F3A. What hypotheses are you trying to test?

mspiegel's picture
Offline
Joined: 07/31/2009
Oops. Looks like we should be

Oops. Looks like we should be throwing an error when "one" is specified as a manifest variable or latent variable.

Steve's picture
Offline
Joined: 07/30/2009
There are a number of people,

There are a number of people, myself included, who doubt that a cross lagged model gives reliable estimates of effects that can be compared across studies. Interpreting the cross lag parameters is particularly difficult since their values (and even signs) can depend on the choice of measurement interval between your observations. I recommend you read Han Oud's 2000 Psychometrika article for some cautionary advice.

With that said, I have several suggestions for implementing your cross-lagged model in OpenMx.

If you are making the assumption of stationarity of your process, try this:

1. "one" is a reserved variable name. It is the only reserved variable name and is used to estimate the means. You should remove the line that says, "latentVars="one","

2. If you have manifest variables, the variances of the first occasion of each variable should be free.

3. You should have a "pre-measurement" latent variable so that the hypothesis of equal residuals will hold for all three occasions of measurement.

4. You should constrain regressions to be equal across time.

5. You should constrain means to be equal across time.

Here is a modified script with those adjustments:

CrossLaggedModel<-mxModel("cross lagged correlation",
        type="RAM",
        manifestVars=c("f1A","f1B","f2A","f2B","f3A","f3B"),
        latentVars=c("f0A", "f0B"),
        mxData(observed=myCrossData, type="raw"),
        mxPath(from=c("f0A","f1A","f2A"), to=c("f1B","f2B","f3B"), 
            arrows=1, free=TRUE, values=.5, labels="AtoB"),
        mxPath(from=c("f0B","f1B","f2B"), to=c("f1A","f2A","f3A"), 
            arrows=1, free=TRUE, values=.5, labels="BtoA"),
        mxPath(from=c("f0A","f1A","f2A"), to=c("f1A","f2A","f3A"), 
            arrows=1, free=TRUE, values=.5, labels="AtoA"),
        mxPath(from=c("f0B","f1B","f2B"), to=c("f1B","f2B","f3B"), 
            arrows=1, free=TRUE, values=.5, labels="BtoB"),
        mxPath(from=c("f1A","f2A","f3A"),
            arrows=2, free=TRUE, values=.8, labels="residualA"),
        mxPath(from=c("f1B","f2B","f3B"), 
            arrows=2, free=TRUE, values=.8, labels="residualB"),
        mxPath(from=c("f0A","f0B","f0A"), to=c("f0A","f0B","f0B"), 
            arrows=2, free=TRUE, values=.8, labels=c("varA", "varB", "covAB")),
        mxPath(from=c("f0A","f0B","f0A"), to=c("f0A","f0B","f0B"), 
            arrows=2, free=TRUE, values=.8, labels=c("varA", "varB", "covAB")),
        mxPath(from=c("f1A","f2A","f3A"), to=c("f1B","f2B","f3B"), 
            arrows=2, free=TRUE, values=.5, labels="residCovAB"),
        mxPath(from="one", to=c("f1A","f1B","f2A","f2B","f3A","f3B"),
            free=TRUE, values=0, labels=c ("mA","mB","mA","mB","mA","mB"))
)

I haven't tried this code, since I don't have your data. Hopefully I've not made any errors in specifying it.

You may also want to look into the dual latent change score model as another way to think about this modeling problem.

feihe's picture
Offline
Joined: 05/30/2012
Error appear in fitting corss lagged model

Hi Steve,

I am working on a problem of detecting autoregressive and cross-lagged effect based on two variables, with 12 time points for each. I don't why every time when I run the code, it shows an error:

"Running cross lagged correlation
Error: The RAM model 'cross lagged correlation' contains raw data but has not specified any means paths."

I thought I defined the path already, so what's the meaning of "means path"? Can you give me some suggestions? I appreciate your help.

Here is my code.

model.test<-data.frame(f1A,f2A,f3A,f4A,f5A,f6A,f7A,f8A,f9A,f10A,f11A,f12A,
f1B,f2B,f3B,f4B,f5B,f6B,f7B,f8B,f9B,f10B,f11B,f12B)
name<-names(model.test)

CrossLaggedModel<-mxModel("cross lagged correlation",
type="RAM",
manifestVars=name,

mxPath(from=name[1:11],to=name[14:24],
arrows=1, free=TRUE, values=0, labels="AtoB"),

mxPath(from=name[13:23],to=name[2:12],
arrows=1, free=TRUE, values=0, labels="BtoA"),

mxPath(from=name[1:11],to=name[2:12],
arrows=1, free=TRUE, values=0, labels="AtoA"),

mxPath(from=name[12:23],to=name[13:24],
arrows=1, free=TRUE, values=0, labels="BtoB"),

mxData(observed=model.test, type="raw")

)

fit <- mxRun(CrossLaggedModel)
summary(fit)

neale's picture
Offline
Joined: 07/31/2009
At least two issues

Hi

In brief, whenever one uses FIML one has to specify a model for the means as well as for the variances and covariances in the structural equation model. If you consult the documentation, particularly the User's Guide section http://openmx.psyc.virginia.edu/docs/OpenMx/latest/TwoModelStylesTwoData... then you will find a brief how-to on providing a model for the means.

The other issue you have is that no variance paths have been specified. This is an easy mistake to make because most path diagrams published in the literature are incomplete from a mathematical (and therefore from a model-specification) point of view. Double-headed arrows should be drawn from variables to themselves in order to specify their residual variance. These will be needed in order to make the model mathematically complete. Again, this is described in the User's guide and can be seen even in the example on the OpenMx home page.

Sorry if this a bit of an RTFM response, but well, it is what it is.

feihe's picture
Offline
Joined: 05/30/2012
Hi, Thank you for your

Hi,

Thank you for your answer. I just start to learn how to use OpenMx, so there are some naive questions need to be solved first. Now I successfully get the estimates for this cross-lagged model, but the estimation is quite weird. So I did simulation, but the estimates are not close enough to the true coefficients I set up. I don't know it's because I didn't make more constraints or the stability of the estimates is not reliable enough. Do you have any idea about this? Thanks a lot!

Fei

Here is my simulation code:

set.seed(234)
N<-500
f1A<-rnorm(N,1,1)
f1B<-rnorm(N,5,2)

f2A<-0.5*f1A+0.1*f1B+ rnorm(N, 0, 0.1)
f2B<-0.5*f1B+3*f1A+ rnorm(N, 0, 0.1)

f3A<-0.5*f2A+0.1*f2B+ rnorm(N, 0, 0.1)
f3B<-0.5*f2B+3*f2A+ rnorm(N, 0, 0.1)

f4A<-0.5*f3A+0.1*f3B+ rnorm(N, 0, 0.1)
f4B<-0.5*f3B+3*f3A+ rnorm(N, 0, 0.1)

f5A<-0.5*f4A+0.1*f4B+ rnorm(N, 0, 0.1)
f5B<-0.5*f4B+3*f4A+ rnorm(N, 0, 0.1)

f6A<-0.5*f5A+0.1*f5B+ rnorm(N, 0, 0.1)
f6B<-0.5*f5B+3*f5A+ rnorm(N, 0, 0.1)

data.simu<-data.frame(f1A,f2A,f3A,f4A,f5A,f6A,f1B,f2B,f3B,f4B,f5B,f6B)
name1<-colnames(data.simu)

CrossLaggedModel1<-mxModel("cross lagged correlation",
type="RAM",
manifestVars=name1,
# latentVars=c("f1A", "f1B"),

mxPath(from=name1[1:5],to=name1[8:12],
arrows=1, free=TRUE, values=1, labels="AtoB"),

mxPath(from=name1[7:11],to=name1[2:6],
arrows=1, free=TRUE, values=1, labels="BtoA"),

mxPath(from=name1[1:5],to=name1[2:6],
arrows=1, free=TRUE, values=1, labels="AtoA"),

mxPath(from=name1[7:11],to=name1[8:12],
arrows=1, free=TRUE, values=1, labels="BtoB"),

mxPath(from="one", to=name1[1:6],arrows=1,
free=TRUE, values=1, labels=c ("mA")),
mxPath(from="one", to=name1[7:12],arrows=1,
free=TRUE, values=1, labels=c ("mB")),

mxPath(from=name1[1:6],
arrows=2, free=TRUE, values=1, labels=c("residualA")),
mxPath(from=name1[7:12],
arrows=2, free=TRUE, values=1, labels=c("residualB")),

mxData(observed=data.simu, type="raw")

)

fit <- mxRun(CrossLaggedModel1)
summary(fit)

neale's picture
Offline
Joined: 07/31/2009
Equated Total Variance & Residual Variance

The simulation generates data with certain variances for the time 1 variables, 1 and 2 for A and B. The equations that generate variables on subsequent occasions add a different amount of residual variance. So to make the model equivalent to the simulation you would need to make different parameters for the initial variances:

mxPath(from=name1[1:6],
arrows=2, free=TRUE, values=1, labels=c("VarA",rep("residualA",5))),
mxPath(from=name1[7:12],
arrows=2, free=TRUE, values=1, labels=c("VarB",rep("residualB",5))),

neale's picture
Offline
Joined: 07/31/2009
neale you dufus, you forgot

neale you dufus, you forgot to tell feihe about the problem with the model for the means! While it might be most instructive to let feihe figure it out, it would also be more frustrating. Feihe to see the solution, look at the following code

mxPath(from="one", to=name1[1:6],arrows=1, 
  free=TRUE, values=1, labels=c (paste("mA",1:6))),
mxPath(from="one", to=name1[7:12],arrows=1,
  free=TRUE, values=1, labels=c (paste("mB",1:6))),

Ta-da! Different means for different occasions of measurement.

feihe's picture
Offline
Joined: 05/30/2012
Binary variable as outcome

Hi,

I have further problem of my model. Instead of using two contineous variables, I have one binary variable and one contineous variable. I have difficulty in interpreating the estimates when comsidering binary variable as outcome. I am not sure the path linkage for binary variable as outcome, is that logistic? Thank you very much.

Fei

neale's picture
Offline
Joined: 07/31/2009
Not logistic

It's the cumulative normal distribution.

p(category=i) = integral from t1 to t2 (normal distribution pdf) where t1 and t2 are the thresholds above and below (t1=-infinity for the lowest category, and t2 = +inf for the highest category).

feihe's picture
Offline
Joined: 05/30/2012
Appreciate your kindly help

Hi neale,

Thank you so much for helping me with patience. I did it correctly following your suggestion and also succeed when I generate the data using different value of parameters assumption. I really appreciate your kindness.

Fei

ebejer's picture
Offline
Joined: 03/18/2010
Hi Steve, Thanks for the

Hi Steve,

Thanks for the script and the referral to the literature and additional model. I ran the script and it gave a 'code red' when all the parameters were 'FREE'. I changed this around a bit and got a couple of code greens. Though setting the parameters also meant that I couldn't get the estimates I wanted.

So, I will start reading about 'how to specify models' from articles that have been published (rather than guessing).

regards
j