Multilevel, longitudinal model (3-level model)

Posted on
No user picture. cdmcdermott221 Joined: 10/09/2018
Hello all,

I know similar questions have been posted here but I'm still unable to figure out the code for my model, as I am super new to OpenMx and structural equation modeling in general. I have intervention data collected at three time-points on children nested within schools. I would like to look at the effect of the intervention over time for the children, but taking the clustering from the schools into account. I'm trying to get my structural equation model to match this mixed model from the nlme package:

MixedModel <- lme(ESA ~ Time + trtGrp + Time*trtGrp,
random = list(School = ~1, idChild = ~1),
weights =varIdent(School),
corr = corCompSymm(form= ~Time),
data=DataSet, na.action="na.omit",
method = "REML")

where ESA is the outcome (emotional self-awareness), Time is as a factor variable (so gives the slopes from Time 1 [ref] to Time 2, and Time 1 to Time 3), trtGrp is the intervention group, and the variance/covariance matrix for the three time-points is compound symmetry. The intercept is random ONLY for Schools. The intercept is fixed for Children, and the slope is fixed for both Children and School.

For structural equation modeling, I've been using a latent growth curve, with the data in wide format. Since the measures are not linear from T1 to T3, I've created two slopes (t1 to t2, and t1 to t3). The bit I'm struggling with is adding a random intercept for schools in OpenMx. Below is the code for a single-level model.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
data=mxData(observed=data1, type="raw")

setting variance to be the same across time points
resVars=mxPath(from=c("ESA_T1", "ESA_T2", "ESA_T3"), arrows=2, free=T, values=c(.5, .5, .5),
labels=c("variance", "variance", "variance"))

resCov1=mxPath(from="ESA_T1", to=c("ESA_T2", "ESA_T3"), arrows=2, free=T, values=c(.2, .2),
labels=c("covar", "covar"))
resCov2=mxPath(from="ESA_T2", to="ESA_T3", arrows=2, free=T, values=.2, labels="covar")

latVars=mxPath(from=c("I", "S", "S2"), arrows=2, connect="unique.pairs", free=c(F, F, F, F, F, F), values=c(0, 0, 0, 0, 0, 0))

intLoads=mxPath(from="I", to=c("ESA_T1", "ESA_T2", "ESA_T3"), arrows=1, free=F,
values=c(1, 1, 1))

slopeLoads=mxPath(from="S", to=c("ESA_T1", "ESA_T2"), arrows=1, free=F,
values=c(0, 1))
slopeLoads2 = mxPath(from="S2", to=c("ESA_T1", "ESA_T3"), arrows=1, free=F,
values=c(0, 1))

manMeans=mxPath(from="one", to=c("ESA_T1", "ESA_T2", "ESA_T3"), arrows=1, free=F,
values=c(0, 0, 0))

latMeans=mxPath(from="one", to=c("I", "S", "S2"), arrows=1, free=T, values=c(1, 1, 1),
labels=c("meanI", "meanS", "meanS2"))

modelTest= mxModel("Test Model", type="RAM", manifestVars=c("ESA_T1", "ESA_T2", "ESA_T3", "trtGrp"),
latentVars=c("I", "S", "S2"), data, resVars, resCov1, resCov2, latVars, intLoads,
slopeLoads, slopeLoads2, manMeans, manMeans1, latMeans, regression, trtVar)

regression = mxPath(from="trtGrp", to=c("I", "S", "S2"), arrows=1, free=TRUE, values=c(1, 1, 1),
labels=c("ireg", "Sreg", "S2reg"))

meantrtGrp = mxPath(from="one", to="trtGrp", arrows=1, free=F, values=0)

TrtVar= mxPath(from="trtGrp", arrows=2, free=F, values=1)

modelTest2= mxModel("Test Model2", type="RAM", manifestVars=c("ESA_recid_1", "ESA_recid_2", "ESA_recid_3", "trtGrp"),
latentVars=c("I", "S", "S2"), data, resVars, resCov1, resCov2, latVars, intLoads,
slopeLoads, slopeLoads2, manMeans, latMeans, regression, meantrtGrp, TrtVar)

GrowthCurvefit = mxRun(modelTest2)
summary(GrowthCurvefit)

~~~~~~~~~~~~~~~~~~~~~~~~~~

With this model, I can match everything to my mixed model except for the school intercept variance (since I haven't added it in here). I have no idea how to add another level, or how to add it so that the only thing it does is give a random intercept for School. If anyone is able to help, I would greatly appreciate it!

Thanks so much!

Replied on Tue, 10/16/2018 - 11:13
Picture of user. jpritikin Joined: 05/23/2012

Here's an example for a random intercept model, xxm-2.R

If you still need help after seeing this example, post your complete script (including a subset of the data or fake data) and I can add the random intercept.