Mon - Fri : 08:00 AM - 5:00 PM

Structural Equation Modeling Using OpenMx

Structural Equation Modeling Using OpenMx


The intial steps to run a full structural equation model using OpenMx mirror those used to run a confirmatory factor analysis using OpenMx. It is necessary to have R installed on your computer and to have downloaded OpenMX.

The present tutorial relies on this running example. To use the OpenMx package, launch R and load the library.

> library(OpenMx)

The present example will rely on a raw data file saved in SPSS format. The foreign library is used to read in SPSS data.

> library(foreign)
> intell<-read.spss("",

This reads in the data from a remote server and saves the file as an object named intell. The names function can be used to preview the variable names in the file.

> names(intell)
[1] "reading"   "writing"   "math"      "analytic"  "simpsons"  "familyguy" "amerdad"

The first four variables represent test scores meant to tap latent intelligence. The last three variables represent reviews of three televsion shows. Before calling the OpenMx function that will estimate the structural equation model, it is helpful to collect the names of the observed variables into one vector (name it “observed”) and the names of the latent variables into another (name it “latents”).

> observed<-names(intell)
> latents<-c("intelligence","humor")

The function used to specify the model is mxModel. The SEM is described as follows:

> sem<-mxModel("Full SEM Model", type="RAM",
+ 	manifestVars=observed,
+ 	latentVars=latents,
+ 	mxPath(from="humor", to=c("simpsons","familyguy","amerdad"),
+ 	free=c(F,T,T), values=c(1,1,1), labels=c("l1","l2","l3"), ),
+ 	mxPath(from="intelligence", to=c("reading","writing","math","analytic"),
+ 	labels=c("l4","l5","l6","l7")),
+ 	mxPath(from="intelligence", to="humor",labels="g1"),
+ 	mxPath(from=observed,arrows=2,labels=c("d1","d2","d3","d4","e1","e2","e3")),
+ 	mxPath(from=latents, arrows=2,free=c(F,T),values=c(1,1)),
+ 	mxData(cov(intell),type="cov",numObs=100)
+ 	)

The model is saved as an object named sem. The first argument in this example names the model. The second argument, type="RAM", tells R that the user is thinking in terms of a path model (RAM stands for “reticular action model”). Alternatively, OpenMx can understand more explicit matrix programming.

The next two arguments, manifestVars and latentVars, assign the names of the observed and unobserved variables, respectively.

The subsequent five commands specify the paths for the model. In the first, one arrow is drawn from the latent variable humor to each of the observed variables simpsons, familyguy, and amerdad. In order to help identify the model, the first loading (from Humor to Simpsons) is constrained to equal one. This is done by specifying free=c(F,T,T), which means that the first loading will not be left as a free parameter but the remaining two will be. The next argument, values=c(1,1,1), is used to 1) specify the value of a constraint for the elements in free set to F (for FALSE); and 2) specify the starting values for the numeric optimizer for the elements in free that were set to T (for TRUE). The labels argument specifies a shorthand name for each parameter to facilitate reading the output.

The next call to mxPath specifies the paths between the latent variable intelligence and the observed variables reading, writing, math, and analytic. Labels are again assigned to name each path. Because all of the respective loadings are left free, no additional arguments are necessary (the free argument defaults to T). An additional call to mxPath specifies the arrow running from intelligence to humor.

The final two calls to mxPath specify the variances for the observed and latent variables. In each case, there is a from argument but no to, and the arrows argument is set equal to 2. This reflects a common convention in drawing path diagrams in which variances are represented with a two-headed arrow. The first of the final two mxPath functions specifies the variances for the observed variables, and the second specifies the variances for the latent variables. In this example, a second model identifying assumption is that the variance for intelligence is constrained to equal 1 using the free and values arguments, while the variance for humor is left free.

The final function, mxData specifies the data source. Although the data were read in raw from a PASW file, the cov function converts the variables into a covariance matrix. The type argument is then set to "cov", for covariance. The reason for this conversion is to keep the estimation in line with LISREL and other packages that default to analyzing a covariance matrix. However, it is possible to leave the data in raw format and specify type="raw". Doing so then defaults to FIML estimation, which is appropriate when there are missing observations in the data file.

To run the model, use the name of the model object as the sole argument to the function mxRun. Save the results into an object named results.

> results<-mxRun(sem)
Running Full SEM Model

View the results using the summary function.

> summary(results)
    reading          writing            math           analytic         simpsons     
 Min.   :0.1884   Min.   :0.1413   Min.   :0.2737   Min.   :0.2147   Min.   :0.1413  
 1st Qu.:0.2237   1st Qu.:0.1681   1st Qu.:0.2847   1st Qu.:0.2367   1st Qu.:0.2210  
 Median :0.8187   Median :0.7063   Median :0.7718   Median :0.7063   Median :0.2777  
 Mean   :0.6047   Mean   :0.5294   Mean   :0.6073   Mean   :0.5659   Mean   :0.3943  
 3rd Qu.:0.8309   3rd Qu.:0.7952   3rd Qu.:0.8205   3rd Qu.:0.8088   3rd Qu.:0.6049  
 Max.   :1.1169   Max.   :0.9316   Max.   :0.9953   Max.   :0.9491   Max.   :0.6897  
   familyguy         amerdad      
 Min.   :0.1826   Min.   :0.1536  
 1st Qu.:0.2395   1st Qu.:0.2016  
 Median :0.2737   Median :0.2917  
 Mean   :0.4297   Mean   :0.4233  
 3rd Qu.:0.6098   3rd Qu.:0.6353  
 Max.   :0.8527   Max.   :0.8443  

   name matrix       row          col  Estimate  Std.Error
1    l4      A   reading intelligence 0.9426912 0.05852687
2    l5      A   writing intelligence 0.8426396 0.05440416
3    l6      A      math intelligence 0.9128734 0.05377982
4    l7      A  analytic intelligence 0.8636460 0.05451091
5    g1      A     humor intelligence 0.2417027 0.05744189
6    l2      A familyguy        humor 1.0150916 0.06320135
7    l3      A   amerdad        humor 1.0995753 0.05726605
8    d1      S   reading      reading 0.2282711 0.03119336
9    d2      S   writing      writing 0.2216014 0.02622611
10   d3      S      math         math 0.1619638 0.02504869
11   d4      S  analytic     analytic 0.2032078 0.02675401
12   e1      S  simpsons     simpsons 0.1169711 0.02202420
13   e2      S familyguy    familyguy 0.2625278 0.03379653
14   e3      S   amerdad      amerdad 0.1518444 0.02795843
15       S     humor        humor 0.5143109 0.06382999

Observed statistics:  28 
Estimated parameters:  15 
Degrees of freedom:  13 
-2 log likelihood:  50.62404 
Saturated -2 log likelihood:  36.94575 
numObs:  100 
Chi-Square:  13.67829 
p:  0.3968841 
AIC (Mx):  -12.32171 
BIC (Mx):  -23.09446 
adjusted BIC: 
RMSEA:  0.0228421 
frontend elapsed time: 0.250772 secs 
backend elapsed time: 0.1482589 secs 

The results mirror those produced by LISREL for the same model.

Still have questions? Contact us!