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

Confirmatory Factor Analysis Using OpenMx

Confirmatory Factor Analysis Using OpenMx


To use 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)

This 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. The present task is to focus on the measurement model for intelligence only; the television variables will be set aside for now.

Before calling the OpenMx function to estimate the confirmatory factor 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<-c("reading","writing","math","analytic")
> latents<-c("intelligence")

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

> cfa<-mxModel("Intelligence Model", type="RAM",
+ 	manifestVars=observed,
+ 	latentVars=latents,
+ 	mxPath(from=latents, to=observed, 
+           free=c(F,T,T,T),values=c(1,1,1,1),labels=c("l1","l2","l3","l4")),
+ 	mxPath(from=observed, arrows=2,labels=c("d1","d2","d3","d4")),
+ 	mxPath(from=latents, arrows=2,labels=c("p1")),
+ 	mxData(cov(intell[,1:4]),type="cov",numObs=100)
+ 	)

The model is saved as an object named cfa. 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 three commands specify the paths for the model. In the first, one arrow is drawn from the latent variable to each of the observed variables. The free argument is used to identify the model by defining which parameters will be constrained. In this case, free is set equal to F (false) for the first loading and T (true) for the remaining three. The subsequent argument, values, sets the value of the constraint. Where free was set to F, the corrsponding number in values is the constraint. Where free is set equal to T, the value is understood to be the starting value for the numeric optimizer. The final argument to mxPath is optional and supplies labels for each of the parameters, which will facilitate reading the output. In this case, the “l” is short for lambda, and the numbers are meant to subscript the particular loading.

The next two mxPath functions specify the variances for the model variables. There is no to argument; instead there is an arrows argument set equal to two. This reflects a common convention in drawing path diagrams in which variances are represented with a two-headed arrow. The names “d1” through “d4” are used to label the variances for the observed variables, and the label “p1” is used to label the variance for the latent variable. Because the model is identified by constraining one factor loading, it is not necessary to constrain the variance of the latent variable (the free argument defaults to T).

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 brackets following the name of the data object subset the file to include only columns one through four (that is, intell[,1:4]), which correspond to the variables used in the model. 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. When a covariance matrix is analyzed, it is necessary to also specify the number of observations (numObs) in the sample.

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(cfa)
Running Intelligence Model

View the results using the summary function.

> summary(results)
    reading          writing            math           analytic     
 Min.   :0.8187   Min.   :0.7063   Min.   :0.7718   Min.   :0.7063  
 1st Qu.:0.8190   1st Qu.:0.7554   1st Qu.:0.7918   1st Qu.:0.7754  
 Median :0.8309   Median :0.7952   Median :0.8205   Median :0.8088  
 Mean   :0.8993   Mean   :0.8071   Mean   :0.8520   Mean   :0.8182  
 3rd Qu.:0.9112   3rd Qu.:0.8469   3rd Qu.:0.8808   3rd Qu.:0.8516  
 Max.   :1.1169   Max.   :0.9316   Max.   :0.9953   Max.   :0.9491  

  name matrix          row          col  Estimate  Std.Error
1   l2      A      writing intelligence 0.8945761 0.04914923
2   l3      A         math intelligence 0.9617760 0.05006481
3   l4      A     analytic intelligence 0.9127264 0.05106145
4   d1      S      reading      reading 0.2234038 0.03110367
5   d2      S      writing      writing 0.2165773 0.02805356
6   d3      S         math         math 0.1687708 0.02551314
7   d4      S     analytic     analytic 0.2047159 0.02713080
8   p1      S intelligence intelligence 0.8935367 0.11400820

Observed statistics:  10 
Estimated parameters:  8 
Degrees of freedom:  2 
-2 log likelihood:  42.523 
Saturated -2 log likelihood:  39.02569 
numObs:  100 
Chi-Square:  3.49731 
p:  0.1740078 
AIC (Mx):  -0.5026897 
BIC (Mx):  -2.856515 
adjusted BIC: 
RMSEA:  0.08652486 
frontend elapsed time: 0.1000688 secs 
backend elapsed time: 0.003484011 secs 

An example of a full structural equation model using OpenMx can be found on the next page.

Still have questions? Contact us!