You are here

3-level longitudinal latent growth curve model

12 posts / 0 new
Last post
cdmcdermott221's picture
Offline
Joined: 10/09/2018 - 09:22
3-level longitudinal latent growth curve model
AttachmentSize
Binary Data OpenMx Single Level Model ESA.R2.18 KB
Image icon Snapshot Data.PNG30.53 KB

Hello all,

I posted this question in the Mixed Effects and Nested Models discussion board, but haven't heard back in a few weeks and my analysis is a bit time-dependent.

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 data from a cluster-randomized RCT, 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 (with the data in long format) 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,
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. I've attached my script to this post, as well as a screenshot of part of my data.

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. Someone did respond to my original post and pointed me to this example: https://github.com/OpenMx/OpenMx/blob/master/inst/models/passing/xxm-2.R

However, I'm still unable to figure out how to make this work for my own data. Again, all I really need is for the intercept to be random at the School level, everything else is a fixed effect. If anyone is able to help, I would greatly appreciate it!

Thanks so much!

jpritikin's picture
Offline
Joined: 05/24/2012 - 00:35
complete runnable example

Can you provide a small subset of the data so that this script is a complete executable example? Providing some data as an image is not helpful.

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

Sorry for the delay, I thought I responded last week but must not have submitted. I clearly misunderstood what you meant by subset, sorry about that! I attached my data in csv format, is that okay? Please let me know if you're unable to use this.

I believe my data needs to be in wide format since it's repeated measures (and I want the covariance matrix to be compound symmetry) and I want two separate slopes from T1 to T2 and T1 to T3. Thanks so much for your help!

File attachments: 
jpritikin's picture
Offline
Joined: 05/24/2012 - 00:35
like this?

Maybe this is the model you want?

mhunter's picture
Offline
Joined: 07/31/2009 - 15:26
Example 3-level models

These two are three-level models:

xxm-3.R

xxm-4.R

If you're just having trouble extending to a 3-level model as an SEM, then these may help. The data are all structured as "tall", not "wide".

jkraemer's picture
Offline
Joined: 12/18/2022 - 02:50
More on 3 Level Models

Dear OpenMx Community,

I am a first-time poster to the forum. I am advanced in R, moderately so in SEM but a newbie for OpenMx. Thanks to the admin for creating an account for me so I can learn from and contribute to the OpenMx community.

This request pertains to helping with the syntax for a 3-level model: people over time but in teams. So, I post under this topic.

I attach "TheIdea.jpg" which is a theorized plot of my idea. Specifically, I seek to test if the gender of team members leads to an assessment that is predictably lower or higher than an anticipated curvilinear (inverted-U) assessment over time. I also attach SEMModel-Sought.jpg. This is what I think the SEM model should look like, the model that I have tried to create in OpenMx. I include this picture, as my error may be conceptual.

I have sought guidance from the examples from this topic as well as the online MPlus user guide. I have also chatted with avid uses of Mplus... but to no avail.

In attempting to generate OpenMX R Code, I was able (I think) to confirm the Level 1 and Level 2 models that I sought to produce. These are MxModelLv1.jpg and MxModelLv2.jpg respectively. A tangent: Is there a better way to diagram a 3 level (or more) model for OpenMx?

I paste the RCode I have been creating below and I attach an excerpt of the data for your reference (DataIndividualForOpenMx.csv).

Any guidance would be appreciated.

Happy New Year!

#Work-in-progress R Code:
library(OpenMx)
 
###
#Team Level [Lv2]
###
 ##If you do not have a model in mind for level 2, you can specify a saturated level by adding all variances and covariances of the endogenous variables
  #https://lavaan.ugent.be/tutorial/multilevel.html
 ##Default starting Values: Variances=1; Covariances/regressions 0.5 (or 0)... but I will try mxAutoStart
  #https://openmx.ssri.psu.edu/thread/1366
 
  #Define Lv2Data
   Lv2Data<-mxData(
                   observed=DataIndividualForOpenMx[!duplicated(DataIndividualForOpenMx$OpenMxTeamNumber),],
                   type="raw",
                   primaryKey="OpenMxTeamNumber"
                  )
   Lv2Data
  #Define the Manifest and Latent Variables
   Lv2Manifests<-c()
   Lv2Manifests
   Lv2AggregationsOfLv1Measures<-paste(c("At3","At4","At5","At6","At7","At8","At9"),"_Agg",sep="")
   Lv2AggregationsOfLv1Measures
   Lv2Latents<-c(Lv2AggregationsOfLv1Measures,"Lv2Intercept","Lv2Slope","Lv2Sqr")
   Lv2Latents
  #Residual Variances of aggregations from indicators on Lv1
   ResVarOfAggregationsFromIndicatorsOnLv1<-mxPath(
                                                   from=Lv2AggregationsOfLv1Measures,
                                                   to=Lv2AggregationsOfLv1Measures,
                                                   arrows=2,
                                                   free=TRUE,
                                                   values=1
                                                  )
   ResVarOfAggregationsFromIndicatorsOnLv1
  #The Covariances between Intercept, Slope and Sqr
   ##This seems to be needed as per: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5875450/
   ##Order is: (a,b), (a,c), (b,c) 
    #As shown by: https://www.rdocumentation.org/packages/OpenMx/versions/2.7.9/topics/mxPath
     Lv2CovBWInterceptSlopeSqr<-mxPath(
                                       from=c("Lv2Intercept","Lv2Slope","Lv2Sqr"),
                                       arrows=2,
                                       connect="unique.bivariate",
                                       free=TRUE,
                                       values=0
                                      )
     Lv2CovBWInterceptSlopeSqr
    #Var of InterceptSlopeSqr
     Lv2VarOfInterceptSlopeSqr<-mxPath(
                                       from=c("Lv2Intercept","Lv2Slope","Lv2Sqr"),
                                       arrows=2,
                                       connect="single",
                                       free=TRUE,
                                       values=1
                                      )
     Lv2VarOfInterceptSlopeSqr
  #Means
   Lv2MeanOfIntercepts<-mxPath(
                               from="one",
                               to="Lv2Intercept",
                               arrows=1,
                               free=TRUE,
                               values=0
                              )
   Lv2MeanOfIntercepts
   Lv2MeanOfSlopes<-mxPath(
                           from="one",
                           to="Lv2Slope",
                           arrows=1,
                           free=TRUE,
                           values=0
                          )
   Lv2MeanOfSlopes
   Lv2MeanOfSqrs<-mxPath(
                         from="one",
                         to="Lv2Sqr",
                         arrows=1,
                         free=TRUE,
                         values=0
                        )
   Lv2MeanOfSqrs
  #Loading Lv2AggregationsOfLv1Measures on Lv2Intercept, Lv2Slope and Lv2Sqr
   Lv2OverTimeLoadingsToLv2Intercept<-mxPath(
                                             from="Lv2Intercept",
                                             to=Lv2AggregationsOfLv1Measures,
                                             arrows=1,
                                             free=FALSE,
                                             values=c(1,1,1,1,1,1,1)
                                            )
   Lv2OverTimeLoadingsToLv2Intercept
   Lv2OverTimeLoadingsToLv2Slope<-mxPath(
                                         from="Lv2Slope",
                                         to=Lv2AggregationsOfLv1Measures,
                                         arrows=1,
                                         free=TRUE,
                                         values=c(0,1,2,3,4,5,6)
                                        )
   Lv2OverTimeLoadingsToLv2Slope
   Lv2OverTimeLoadingsToLv2Sqr<-mxPath(
                                       from="Lv2Sqr",
                                       to=Lv2AggregationsOfLv1Measures,
                                       arrows=1,
                                       free=TRUE,
                                       values=c(0,1,4,9,16,25,36)
                                      )
   Lv2OverTimeLoadingsToLv2Sqr
  #Build Lv2 Model
   MxModelLv2<-mxModel(
                       model="MxModelLv2", type="RAM", 
                       data=Lv2Data,
                       manifestVars=Lv2Manifests, latentVars=Lv2Latents,
                       ResVarOfAggregationsFromIndicatorsOnLv1,
                       Lv2CovBWInterceptSlopeSqr,
                       Lv2VarOfInterceptSlopeSqr,
                       Lv2MeanOfIntercepts,
                       Lv2MeanOfSlopes,
                       Lv2MeanOfSqrs,
                       Lv2OverTimeLoadingsToLv2Intercept,
                       Lv2OverTimeLoadingsToLv2Slope,
                       Lv2OverTimeLoadingsToLv2Sqr
                      )#end MxModelLv2
 
 
###
#Individual Level [Lv1]
###
 
 ##Lv1 Data
   Lv1Data<-mxData(
                   observed=DataIndividualForOpenMx,
                   type="raw",
                   primaryKey="PrimaryKeyInteger"
                  )
   Lv1Data
 ##Define the Manifest and Latent Variables
   Lv1Manifests<-c("At3","At4","At5","At6","At7","At8","At9","gender_binary")
   Lv1Manifests
   Lv1Latents<-c("Lv1Intercept","Lv1Slope","Lv1Sqr")
   Lv1Latents
 ##Connect Lv1Data to Lv2Data
   Lv1Links<-paste("MxModelLv2.",c("At3","At4","At5","At6","At7","At8","At9"),"_Agg",sep="")
   Lv1Links
   ConnectingPath<-mxPath(
                          from=Lv1Links,
                          to=c("At3","At4","At5","At6","At7","At8","At9"),
                          free=FALSE,
                          values=1,
                          joinKey="OpenMxTeamNumber"
                         )
   ConnectingPath
 ##Vars of InterceptSlopeSqr
   Lv1VarOfInterceptSlopeSqr<-mxPath(
                                     from=c("Lv1Intercept","Lv1Slope","Lv1Sqr"),
                                     arrows=2,
                                     connect="single",
                                     free=TRUE,
                                     values=0
                                    )
   Lv1VarOfInterceptSlopeSqr
 ##Means of InterceptSlopeSqr
   Lv1MeanOfIntercepts<-mxPath(
                               from="one",
                               to="Lv1Intercept",
                               arrows=1,
                               free=TRUE,
                               values=0
                              )
   Lv1MeanOfIntercepts
   Lv1MeanOfSlopes<-mxPath(
                           from="one",
                           to="Lv1Slope",
                           arrows=1,
                           free=TRUE,
                           values=0
                          )
   Lv1MeanOfSlopes
   Lv1MeanOfSqrs<-mxPath(
                         from="one",
                         to="Lv1Sqr",
                         arrows=1,
                         free=TRUE,
                         values=0
                        )
   Lv1MeanOfSqrs
 ##The Covariances between Intercept, Slope and Sqr (https://www.rdocumentation.org/packages/OpenMx/versions/2.7.9/topics/mxPath)
   Lv1CovBWInterceptSlopeSqr<-mxPath(
                                     from=c("Lv1Intercept","Lv1Slope","Lv1Sqr"),
                                     arrows=2,
                                     connect="unique.bivariate",
                                     free=TRUE,
                                     values=0
                                    )
   Lv1CovBWInterceptSlopeSqr
 
 ##Loadings of Repeated Measures on Intercept (All of these are fixed to 1 in a latent Growth Curve)
   Lv1OverTimeLoadingsToLv1Intercept<-mxPath(
                                             from="Lv1Intercept",
                                             to=c("At3","At4","At5","At6","At7","At8","At9"),
                                             arrows=1,
                                             free=FALSE,
                                             values=1
                                            )
   Lv1OverTimeLoadingsToLv1Intercept
  #Loadings of Repeated Measures on Slope (These start at 0 and increase in increments of 1)
   Lv1OverTimeLoadingsToLv1Slope<-mxPath(
                                         from="Lv1Slope",
                                         to=c("At3","At4","At5","At6","At7","At8","At9"),
                                         arrows=1,
                                         free=FALSE,
                                         values=c(0,1,2,3,4,5,6)
                                        )
   Lv1OverTimeLoadingsToLv1Slope
  #Loadings of Repeated Measures on Sqr (These are "slope" values ^2... e.g. 0^2, 1^2, 2^2, 3^2... etc)
   Lv1OverTimeLoadingsToLv1Sqr<-mxPath(
                                       from="Lv1Sqr",
                                       to=c("At3","At4","At5","At6","At7","At8","At9"),
                                       arrows=1,
                                       free=FALSE,
                                       values=c(0,1,4,9,16,25,36)
                                      )
  Lv1OverTimeLoadingsToLv1Sqr
 
  #ResidualVariancseOfRepeatedMeasures
   Lv1ResidualVariancesOfRepeatedMeasures<-mxPath(
                                                  from=c("At3","At4","At5","At6","At7","At8","At9"),
                                                  to=c("At3","At4","At5","At6","At7","At8","At9"),
                                                  arrows=2,
                                                  free=TRUE,
                                                  values=1
                                                  )
   Lv1ResidualVariancesOfRepeatedMeasures
 
  #Covariances of Intercept, Slope and Sqr
   #Order is: #(a,a), (a,b), (a,c), (b,b), (b,c), (c,c) 
   #As shown by: https://www.rdocumentation.org/packages/OpenMx/versions/2.7.9/topics/mxPath
   Lv1CovBWInterceptSlopeAndSqr<-mxPath(
                                        from=c("Lv1Intercept","Lv1Slope","Lv1Sqr"),
                                        arrows=2,
                                        free=TRUE,
                                        values=0,
                                        connect="unique.bivariate"
                                     )
   Lv1CovBWInterceptSlopeAndSqr
 
 ##IV (gender_binary) as a predictor for variability from quadradic trajectory
  #Vars of gender_binary
   Lv1VarOfGender<-mxPath(
                          from="gender_binary",
                          arrows=2,
                          free=TRUE,
                          values=1
                         )
   Lv1VarOfGender
  #Means of Gender
   Lv1MeanOfGender<-mxPath(
                           from="one",
                           to="gender_binary",
                           arrows=1,
                           free=TRUE,
                           values=0
                          )
   Lv1MeanOfGender
  #Gender Predicting Repeated Measures
   Lv1GenderToOverTime<-mxPath(
                               from="gender_binary",
                               to=c("At3","At4","At5","At6","At7","At8","At9"),
                               arrows=1,
                               free=TRUE,
                               values=c(0,0,0,0,0,0,0)
                              )
   Lv1GenderToOverTime
 
 
 ##Building the Model
   MxModelLv1<-mxModel(
                       model="MxModelLv1", type="RAM",
                       manifestVars=Lv1Manifests, latentVars=Lv1Latents,
                       mxModel(model=MxModelLv2),
                       Lv1Data,
                       ConnectingPath,
                       Lv1VarOfInterceptSlopeSqr,
                       Lv1MeanOfIntercepts,
                       Lv1MeanOfSlopes,
                       Lv1MeanOfSqrs,
                       Lv1CovBWInterceptSlopeAndSqr,
                       Lv1OverTimeLoadingsToLv1Intercept,
                       Lv1OverTimeLoadingsToLv1Slope,
                       Lv1OverTimeLoadingsToLv1Sqr,
                       Lv1ResidualVariancesOfRepeatedMeasures,
                       Lv1CovBWInterceptSlopeAndSqr,
                       Lv1VarOfGender, Lv1GenderToOverTime, Lv1GenderToOverTime
                      )#end StudentGrowthIntSlopeAndSqrModel
 
 
##Trying to run...
   tmpModel1<-mxAutoStart(MxModelLv1) #This (I think) finds better starting values (ii)
    #Error: Foreign key 'OpenMxTeamNumber' not found in  MxModelLv1.data
   Fit_Growth<-mxRun(MxModelLv1)
    #In model 'MxModelLv1' Optimizer returned a non-zero status code 6. The model does not satisfy the first-order optimality conditions to the required  accuracy, and no improved point for the merit function could be found during the final linesearch (Mx status RED) ...
   mxCheckIdentification(MxModelLv1)
    #... Model is not locally identified
AdminHunter's picture
Offline
Joined: 03/01/2013 - 11:03
Specifically?

Do you have a specific question, or do you just want us to painstaking inspect your 300-line model script?

To be clear, we are happy to help. I just do not understand what you are asking for.

jkraemer's picture
Offline
Joined: 12/18/2022 - 02:50
Problems with Levels in OpenMx

AdminHunter,

Thank you for your reply. I apologize for my delayed post. I just became aware of your reply yesterday. I will now make a point of manually checking back at a much quicker rate. Anyway...

It seems that your 2 biggest concerns were: (1) focus of inquiry and (2) length of code excerpt. Let me try to address each in turn...

1)Focus of inquiry: Whenever I "link" between levels OpenMx replies: "Error: Foreign key XXX' not found in XXX.dat"
However, when I check the Data of Level 2 (~Team~) and Level 1 (~Individual~) the variable I designate as the "Foreign key" is present. I think there is a syntax issue that I cannot find. If willing, please check the code starting with "Lv2Data<-mxData(" and "Lv1Data<-mxData(". Am I designating the MxData assignment correctly? There may may also be a issue with the code under "####Connect Lv1Data to Lv2Data". Is there something else you have in mind that might cause an error related to "linking" between levels?

2) length of code excerpt: To address this concern, I removed the slope and square terms. It reduces the code somewhat. Stepping away from the lose in conceptual sense, I hope this reduced code and accompanying graphs help diagnose what I think is a syntax problem. I feel limited in my ability to reduce further, as I want to provide a "reproducible error". If you think there is a way to further reduce the code length... just let me know and I am willing to do so... and willing to do so promptly.

I often have problems with "starting values". There are rules of thumb etc that I try to follow. I understand that mxAutoStart() can help with this issue. Can you confirm I am using it correctly?

PS: I live and work in a developing nation. Though MPlus etc may have more simple syntax, PhD students and other researchers here are eager to learn OpenMx because it helps them cross a paywall that they cannot otherwise cross. Think of me as a bridge... So... we all thank you for working through this with me.

The reduced code is below:

 ####Dir Pointers ****Put the path to the files on your local drive here****
   SourceDirPtr<-"/home/jkraemer/Documents/JKGDrive/XC-JK/PokingTheTrajectory/OpenMxForum/"
   SinkDirPtr<-"/home/jkraemer/Documents/JKGDrive/XC-JK/PokingTheTrajectory/OpenMxForum/"
   SourceDirPtr
   SinkDirPtr
 
##Work-in-progress R Code:
 library(OpenMx)
 
######
##Putting all items (missing or NOT) from DataIndividualForOpenMx in to a data frame
######
  SourcePhrase<-paste(SourceDirPtr,"DataIndividualForOpenMx.csv",sep="")
  SourcePhrase
  DataIndividualForOpenMx<-read.csv(SourcePhrase,header=TRUE)
  head(DataIndividualForOpenMx)
  colnames(DataIndividualForOpenMx)
 
######
##Team Level [Lv2]
######
 
  ##Define Lv2Data
   Lv2Data<-mxData(
                   observed=DataIndividualForOpenMx[!duplicated(DataIndividualForOpenMx$OpenMxTeamNumber),],
                   type="raw",
                   primaryKey="OpenMxTeamNumber"
                  )
   Lv2Data
  ##Define the Manifest and Latent Variables
   Lv2Manifests<-c()
   Lv2Manifests
   Lv2AggregationsOfLv1Measures<-paste(c("At3","At4","At5","At6","At7","At8","At9"),"_Agg",sep="")
   Lv2AggregationsOfLv1Measures
   Lv2Latents<-c(Lv2AggregationsOfLv1Measures,"Lv2Intercept")
   Lv2Latents
  ##Residual Variances of aggregations from indicators on Lv1
   ResVarOfAggregationsFromIndicatorsOnLv1<-mxPath(
                                                   from=Lv2AggregationsOfLv1Measures,
                                                   to=Lv2AggregationsOfLv1Measures,
                                                   arrows=2,
                                                   free=TRUE,
                                                   values=1
                                                  )
   ResVarOfAggregationsFromIndicatorsOnLv1
    ##Var of Intercept
     Lv2VarOfIntercept<-mxPath(
                                    from=c("Lv2Intercept"),
                                    arrows=2,
                                    connect="single",
                                    free=TRUE,
                                    values=1
                                   )
     Lv2VarOfIntercept
  ##Means
   Lv2MeanOfIntercepts<-mxPath(
                               from="one",
                               to="Lv2Intercept",
                               arrows=1,
                               free=TRUE,
                               values=0
                              )
   Lv2MeanOfIntercepts
  ##Loading Lv2AggregationsOfLv1Measures on Lv2Intercept
   Lv2OverTimeLoadingsToLv2Intercept<-mxPath(
                                             from="Lv2Intercept",
                                             to=Lv2AggregationsOfLv1Measures,
                                             arrows=1,
                                             free=FALSE,
                                             values=c(1,1,1,1,1,1,1)
                                            )
   Lv2OverTimeLoadingsToLv2Intercept
  ##Build Lv2 Model
   MxModelLv2<-mxModel(
                       model="MxModelLv2", type="RAM", 
                       data=Lv2Data,
                       manifestVars=Lv2Manifests, latentVars=Lv2Latents,
                       ResVarOfAggregationsFromIndicatorsOnLv1,
                       Lv2MeanOfIntercepts, Lv2VarOfIntercept,
                       Lv2OverTimeLoadingsToLv2Intercept
                      )##end MxModelLv2
 
 ####Export Picture
##   tmpPhrase<-paste(SinkDirPtr,"Lv2Model.dot",sep="")
##   omxGraphviz(MxModelLv2,tmpPhrase)
##   system(paste("display ", tmpPhrase, sep=""))
 
 
######
##Individual Level [Lv1]
######
 
 ####Lv1 Data
   Lv1Data<-mxData(
                   observed=DataIndividualForOpenMx,
                   type="raw",
                   primaryKey="PrimaryKeyInteger"
                  )
   Lv1Data
 ####Define the Manifest and Latent Variables
   Lv1Manifests<-c("At3","At4","At5","At6","At7","At8","At9","gender_binary")
   Lv1Manifests
   Lv1Latents<-c("Lv1Intercept")
   Lv1Latents
 ####Connect Lv1Data to Lv2Data
   Lv1Links<-paste("MxModelLv2.",c("At3","At4","At5","At6","At7","At8","At9"),"_Agg",sep="")
   Lv1Links
   ConnectingPath<-mxPath(
                          from=Lv1Links,
                          to=c("At3","At4","At5","At6","At7","At8","At9"),
                          free=FALSE,
                          values=1,
                          joinKey="OpenMxTeamNumber"
                         )
   ConnectingPath
 ####Vars of Intercept
   Lv1VarOfIntercept<-mxPath(
                             from=c("Lv1Intercept"),
                             arrows=2,
                             connect="single",
                             free=TRUE,
                             values=0
                            )
   Lv1VarOfIntercept
 ####Means of Intercept
   Lv1MeanOfIntercepts<-mxPath(
                               from="one",
                               to="Lv1Intercept",
                               arrows=1,
                               free=TRUE,
                               values=0
                              )
   Lv1MeanOfIntercepts
 
 ####Loadings of Repeated Measures on Intercept (All of these are fixed to 1 in a latent Growth Curve)
   Lv1OverTimeLoadingsToLv1Intercept<-mxPath(
                                             from="Lv1Intercept",
                                             to=c("At3","At4","At5","At6","At7","At8","At9"),
                                             arrows=1,
                                             free=FALSE,
                                             values=1
                                            )
   Lv1OverTimeLoadingsToLv1Intercept
 
  ##ResidualVariancseOfRepeatedMeasures
   Lv1ResidualVariancesOfRepeatedMeasures<-mxPath(
                                                  from=c("At3","At4","At5","At6","At7","At8","At9"),
                                                  to=c("At3","At4","At5","At6","At7","At8","At9"),
                                                  arrows=2,
                                                  free=TRUE,
                                                  values=1
                                                  )
   Lv1ResidualVariancesOfRepeatedMeasures
 
 
 ####IV (gender_binary)
  ##Vars of gender_binary
   Lv1VarOfGender<-mxPath(
                          from="gender_binary",
                          arrows=2,
                          free=TRUE,
                          values=1
                         )
   Lv1VarOfGender
  ##Means of Gender
   Lv1MeanOfGender<-mxPath(
                           from="one",
                           to="gender_binary",
                           arrows=1,
                           free=TRUE,
                           values=0
                          )
   Lv1MeanOfGender
 
  ##Gender Predicting Repeated Measures
   Lv1GenderToOverTime<-mxPath(
                               from="gender_binary",
                               to=c("At3","At4","At5","At6","At7","At8","At9"),
                               arrows=1,
                               free=TRUE,
                               values=c(0,0,0,0,0,0,0)
                              )
   Lv1GenderToOverTime
 
 
 ####Building the Model
   MxModelLv1<-mxModel(
                       model="MxModelLv1", type="RAM",
                       manifestVars=Lv1Manifests, latentVars=Lv1Latents,
                       mxModel(model=MxModelLv2),
                       Lv1Data,
                       ConnectingPath,
                       Lv1VarOfIntercept,
                       Lv1MeanOfIntercepts,
                       Lv1OverTimeLoadingsToLv1Intercept,
                       Lv1ResidualVariancesOfRepeatedMeasures,
                       Lv1VarOfGender, Lv1GenderToOverTime
                      )##end MxModelLv1
 
  ####Export Picture
##   tmpPhrase<-paste(SinkDirPtr,"Lv1Model.dot",sep="")
##   omxGraphviz(MxModelLv1,tmpPhrase)
##   system(paste("display ", tmpPhrase, sep=""))
 
####Trying to run...
   tmpModel1<-mxAutoStart(MxModelLv1) ##This (I think) finds better starting values (ii)
    ##Error: Foreign key 'OpenMxTeamNumber' not found in  MxModelLv1.data
 
######After finding starting values... try to run
######After finding starting values... try to run
######After finding starting values... try to run
######After finding starting values... try to run
######After finding starting values... try to run
   Fit_Growth<-mxRun(MxModelLv1)
File attachments: 
jkraemer's picture
Offline
Joined: 12/18/2022 - 02:50
Problems with Levels in OpenMx ... data

Sorry... for your convenience, I re-post the data.

File attachments: 
AdminHunter's picture
Offline
Joined: 03/01/2013 - 11:03
mxAutoStart is not suitable for multilevel models

Ahh. I understand the question and know the solution now. Thank you for clarifying!

mxAutoStart() does not work for multilevel models (any model that uses foreign keys). The immediate solution for you is to just not use that function. The model ran fine for me without it.

The immediate solution for the OpenMx development team is to catch this situation and give an informative and useful error message. Longer term we might extend mxAutoStart() to multilevel models, but have no current plans to do so.

Sorry for the uninformative error!

jkraemer's picture
Offline
Joined: 12/18/2022 - 02:50
Starting Values...

Thank you for the prompt response. I will try without mxAutoStart(). I am glad to know you could run it without mxAutoStart(). Is there any guidance that you can provide about starting values for multi-level models? Will the same "rules of thumb" work for multi-level models as for "single" level models?

AdminHunter's picture
Offline
Joined: 03/01/2013 - 11:03
Same

The same general guidance applies to multi-level models as other models. (1) Make sure the variances are positive, (2) Make sure the covariances and regression effects are not too large, (3) Make sure the means are plausibly close to the sample means.