Reputation: 783
I'm trying to figure out how to properly add a predictor of the slope and intercept in a latent growth curve model in the OpenMx package for R.
I would like to predict the slope and intercept from, say, gender in a very simple growth curve model. For the sake of this question, let's say it's the model described in the documentation here.
What would I add to include a time-invariant predictor of the slope and intercept? In MPlus I would write i on male;
and I would get an estimate of the path from the gender variable to the latent intercept. To do the same thing in OpenMx would I simply add that path specification? Would I need override any defaults so that I don't estimate a variance or mean path for this manifest variable (or so I do)?
For easy reference, below is the code for the simple growth curve, and what I've added for the predictor. However, when I add the predictor I get the error 'covariance matrix is not positive-definite'. This is what I'm seeing in real data too.
n.b., this question is cross posted on the OpenMx forum.
myLongitudinalData=data.frame(x1=rnorm(100),
x2=rnorm(100),
x3=rnorm(100),
x4=rnorm(100),
x5=rnorm(100),
male=round(runif(100,0,1)))
require(OpenMx)
growthCurveModel <- mxModel("Linear Growth Curve Model Path Specification",
type="RAM",
mxData(
myLongitudinalData,
type="raw"
),
manifestVars=c("x1","x2","x3","x4","x5"),
latentVars=c("intercept","slope"),
# residual variances
mxPath(
from=c("x1","x2","x3","x4","x5"),
arrows=2,
free=TRUE,
values = c(1, 1, 1, 1, 1),
labels=c("residual","residual","residual","residual","residual")
),
# latent variances and covariance
mxPath(
from=c("intercept","slope"),
arrows=2,
connect="unique.pairs",
free=TRUE,
values=c(1, 1, 1),
labels=c("vari", "cov", "vars")
),
# intercept loadings
mxPath(
from="intercept",
to=c("x1","x2","x3","x4","x5"),
arrows=1,
free=FALSE,
values=c(1, 1, 1, 1, 1)
),
# slope loadings
mxPath(
from="slope",
to=c("x1","x2","x3","x4","x5"),
arrows=1,
free=FALSE,
values=c(0, 1, 2, 3, 4)
),
# manifest means
mxPath(
from="one",
to=c("x1", "x2", "x3", "x4", "x5"),
arrows=1,
free=FALSE,
values=c(0, 0, 0, 0, 0)
),
# latent means
mxPath(
from="one",
to=c("intercept", "slope"),
arrows=1,
free=TRUE,
values=c(1, 1),
labels=c("meani", "means")
)
) # close model
growthCurveFit <- mxRun(growthCurveModel)
summary(growthCurveFit)
My attempt to add a predictor--I add the gender variable to the manifest variables, and then create a path definition from it to the latent variables (toward the bottom):
growthCurveModel2 <- mxModel("Linear Growth Curve Model Path Specification",
type="RAM",
mxData(
myLongitudinalData,
type="raw"
),
manifestVars=c("x1","x2","x3","x4","x5","male"),
latentVars=c("intercept","slope"),
# residual variances
mxPath(
from=c("x1","x2","x3","x4","x5"),
arrows=2,
free=TRUE,
values = c(1, 1, 1, 1, 1),
labels=c("residual","residual","residual","residual","residual")
),
# latent variances and covariance
mxPath(
from=c("intercept","slope"),
arrows=2,
connect="unique.pairs",
free=TRUE,
values=c(1, 1, 1),
labels=c("vari", "cov", "vars")
),
# intercept loadings
mxPath(
from="intercept",
to=c("x1","x2","x3","x4","x5"),
arrows=1,
free=FALSE,
values=c(1, 1, 1, 1, 1)
),
# slope loadings
mxPath(
from="slope",
to=c("x1","x2","x3","x4","x5"),
arrows=1,
free=FALSE,
values=c(0, 1, 2, 3, 4)
),
# manifest means
mxPath(
from="one",
to=c("x1", "x2", "x3", "x4", "x5"),
arrows=1,
free=FALSE,
values=c(0, 0, 0, 0, 0)
),
# latent means
mxPath(
from="one",
to=c("intercept", "slope"),
arrows=1,
free=TRUE,
values=c(1, 1),
labels=c("meani", "means")
),
mxPath(
from="male",
to=c("intercept", "slope"),
arrows=1,
free=TRUE,
values=c(1,1),
labels=c("iOnMale", "sOnMale"))
) # close model
growthCurveFit2 <- mxRun(growthCurveModel2)
summary(growthCurveFit2)
Upvotes: 2
Views: 888
Reputation: 783
I believe I figured it out--one must specify the predictor's variance and mean structure paths, in line with this diagram from Kline's SEM book (2011):
In MPlus, I think that the default for regressing the latent slope and intercept on a predictor is to set the mean structure path to 0 and the variance path to 1. I'm not 100% sure about this, but this gave me an identical parameterization and very similar estimates. So, I added this snippet to the second model above:
#Predictor mean structure
mxPath(
from="one",
to="male",
arrows=1,
free=FALSE,
values = 0
),
#Predictor Variance
mxPath(
from="male",
arrows=2,
free=FALSE,
values = 1
)
Kline, R. B. (2011). Principles and practice of structural equation modeling. Guilford press.
Upvotes: 0