Quick Overview
==============
This document provides a quick overview of the capabilities of OpenMx in handling everything from simple calculations to optimization of complex multiple group models. Note that this overview focuses on matrix specification of OpenMx models, and that all these models can equally well be developed using path specification. We start with a matrix algebra example, followed by an optimization example. We end this quick overview with a twin analysis example, as the majority of prior Mx users will be familiar with this type of analysis. We plan to expand this overview with examples more relevant to other applications of structural equation modeling. While we provide the scripts here, we will not discuss every detail, as that is done more systematically in the next example shown in two model styles and two data styles. Then we describe in detail a series of models using path specification, followed by the same examples in matrix specification.
The OpenMx scripts for the examples in this overview are available in the following files:
* http://openmx.psyc.virginia.edu/repoview/1/trunk/demo/MatrixAlgebra.R
* http://openmx.psyc.virginia.edu/repoview/1/trunk/demo/BivariateCorrelation.R
* http://openmx.psyc.virginia.edu/repoview/1/trunk/demo/UnivariateTwinAnalysis.R
Simple OpenMx Script
--------------------
We will start by showing some of the main features of OpenMx using simple examples. For those familiar with Mx, it is basically a matrix interpreter combined with a numerical optimizer to allow fitting statistical models. Of course you do not need OpenMx to perform matrix algebra as that can already be done in R. However, to accommodate flexible statistical modeling of the type of models typically fit in Mx, Mplus or other SEM packages, special kinds of matrices and functions are required which are bundled in OpenMx. We will introduce key features of OpenMx using a matrix algebra example. Remember that R is object-oriented, such that the results of operations are objects, rather than just matrices, with various properties/characteristics attached to them. We will describe the script line by line; a link to the complete script is `here
`_.
Say, we want to create two matrices, **A** and **B**, each of them a 'Full' matrix with 3 rows and 1 column and with the values 1, 2 and 3, as follows:
.. math::
:nowrap:
\begin{eqnarray*}
A = \left[ \begin{array}{r} 1 \\ 2 \\ 3 \\ \end{array} \right]
& B = \left[ \begin{array}{r} 1 \\ 2 \\ 3 \\ \end{array} \right]
\end{eqnarray*}
we use the ``mxMatrix`` command, and define the type of the matrix (``type=``), number of rows (``nrow=``) and columns (``ncol=``), its specifications (``free=``) and starting values (``values=``), optionally labels (``labels=``), upper (``ubound=``) and lower (``lbound=``) bounds>, and a name (``name=``). The matrix **A** will be stored as the object 'A'.
.. code-block:: r
mxMatrix(
type="Full",
nrow=3,
ncol=1,
values=c(1,2,3),
name='A'
)
mxMatrix(
type="Full",
nrow=3,
ncol=1,
values=c(1,2,3),
name='B'
)
Assume we want to calculate the (1) the sum of the matrices **A** and **B**, (2) the element by element multiplication (Dot product) of **A** and **B**, (3) the transpose of matrix **A**, and the (4) outer and (5) inner products of the matrix **A**, using regular matrix multiplication, i.e.:
.. math::
:nowrap:
\begin{eqnarray}
q2 & = & A + B \\
q1 & = & A . A \\
q3 & = & t(A) \\
q4 & = & A * t(A) \\
q5 & = & t(A) * A
\end{eqnarray}
we invoke the ``mxAlgebra`` command which performs an algebra operation between previously defined matrices. Note that in R, regular matrix multiplication is represented by ``\%*\%`` and dot multiplication as ``*``. We also assign the algebras a name to refer back to them later:
.. code-block:: r
mxAlgebra(
A + B,
name='q1'
)
mxAlgebra(
A * A,
name='q2'
)
mxAlgebra(
t(A),
name='q3'
)
mxAlgebra(
A %*% t(A),
name='q4'
)
mxAlgebra(
t(A) %*% A,
name='q5'
)
For the algebras to be evaluated, they become arguments of the ``mxModel`` command, as do the defined matrices, each separated by comma's. The model, which is here given the name 'algebraExercises', is then executed by the ``mxRun`` command, as shown in the full code below:
.. code-block:: r
require(OpenMx)
algebraExercises `_.
Say, we have collected data on two variables **X** and **Y** in 1000 individuals, and R descriptive statistics has shown that the correlation between them is 0.5. For the sake of this example, we used another built-in function in the R package MASS, namely ``mvrnorm``, to generate multivariate normal data for 1000 individuals with means of 0.0, variances of 1.0 and a correlation (``rs``) of 0.5 between **X** and **Y**. Note the that first argument of ``mvrnorm`` is the sample size, the second the vector of means, and the third the covariance matrix to be simulated. We save the data in the object ``xy`` and create a vector of labels for the two variables in ``selVars`` which is used in the ``dimnames`` statement later on. The R functions ``summary()`` and ``cov()`` are used to verify that the simulations appear OK.
.. code-block:: r
#Simulate Data
require(MASS)
set.seed(200)
rs=.5
xy summary(bivCorFit)
X Y
Min. :-2.942561 Min. :-3.296159
1st Qu.:-0.633711 1st Qu.:-0.596177
Median :-0.004139 Median :-0.010538
Mean : 0.032116 Mean :-0.004884
3rd Qu.: 0.739236 3rd Qu.: 0.598326
Max. : 4.173841 Max. : 4.006771
name matrix row col parameter estimate error estimate
1 expMean 1 1 0.032116456 0.02228409
2 expMean 1 2 -0.004883803 0.02235021
3 Chol 1 1 1.004631642 0.01575904
4 Chol 2 1 0.479130899 0.02099642
5 Chol 2 2 0.874055066 0.01376876
Observed statistics: 2000
Estimated parameters: 5
Degrees of freedom: 1995
-2 log likelihood: 5415.772
Saturated -2 log likelihood:
Chi-Square:
p:
AIC (Mx): 1425.772
BIC (Mx): -4182.6
adjusted BIC:
RMSEA: 0
If we want to test whether the covariance/correlation is significantly different from zero, we could fit a submodel and compare it with the previous saturated model. Given that this model is essentially the same as the original, except for the covariance, we create a new mxModel (named ``bivCorModelSub``) with as first argument the old model (named ``bivCorModel``). Then we only have to specify the matrix that needs to be changed, in this case the lower triangular matrix becomes essentially a diagonal matrix, obtained by fixing the off-diagonal elements to zero in the ``free`` and ``values`` arguments
.. code-block:: r
#Test for Covariance=Zero
bivCorModelSub `_.
includes both the twin data simulation and several OpenMx scripts to analyze the data. We will describe each of the parts in turn and include the code for the specific part in the code blocks.
First, we simulate twin data using the ``mvrnorm`` R function. If the additive genetic factors (**A**) account for 50% of the total variance and the shared environmental factors (**C**) for 30%, thus leaving 20% explained by specific environmental factors (**E**), then the expected MZ twin correlation is ``a^2 + c^2`` or 0.8 in this case, and the expected DZ twin correlation is 0.65, calculated as ``.5*a^2 + c^2``. We simulate 1000 pairs of MZ and DZ twins each with zero means and a correlation matrix according to the values listed above. We run some basic descriptive statistics on the simulated data, using regular R functions.
.. code-block:: r
require(OpenMx)
require(MASS)
set.seed(200)
a2