You are here

Multilevel, longitudinal model (3-level model)

3 posts / 0 new
Last post
cdmcdermott221's picture
Joined: 10/09/2018 - 09:22
Multilevel, longitudinal model (3-level model)

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)


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!

jpritikin's picture
Joined: 05/24/2012 - 00:35
random intercept

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.

cdmcdermott221's picture
Joined: 10/09/2018 - 09:22

I tried to base my script off that example but still ran into problems. I've attached my full script and a screenshot of my data here. I removed the treatment variable in the SEM code to just focus on the random intercept.

Thanks so much!