Update Users Guide pages A through F for the expectation-fit change.
[openmx:openmx.git] / docs / source / DefinitionMeans_Matrix.rst
1 .. _definitionmeans-matrix-specification:
2
3 Definition Variables, Matrix Specification
4 ==========================================
5
6 This example will demonstrate the use of OpenMx definition variables with the implementation of a simple two group dataset.  What are definition variables?  Essentially, definition variables can be thought of as observed variables which are used to change the statistical model on an individual case basis.  In essence, it is as though one or more variables in the raw data vectors are used to specify the statistical model for that individual.  Many different types of statistical models can be specified in this fashion; some can be readily specified in standard fashion, and some that cannot.  To illustrate, we implement a two-group model.  The groups differ in their means but not in their variances and covariances.  This situation could easily be modeled in a regular multiple group fashion - it is only implemented using definition variables to illustrate their use.  The results are verified using summary statistics and an Mx 1.0 script for comparison is also available.
7
8 Mean Differences
9 ----------------
10
11 The example shows the use of definition variables to test for mean differences. It is available in the following file:
12
13 * http://openmx.psyc.virginia.edu/svn/trunk/demo/DefinitionMeans_MatrixRaw.R
14
15 A parallel version of this example, using path specification of models rather than matrices, can be found here:
16
17 * http://openmx.psyc.virginia.edu/svn/trunk/demo/DefinitionMeans_PathRaw.R
18
19
20 Statistical Model
21 ^^^^^^^^^^^^^^^^^
22
23 Algebraically, we are going to fit the following model to the observed x and y variables:
24
25 .. math::
26    :nowrap:
27    
28    \begin{eqnarray*} 
29    x_{i} = \mu_{x} + \beta_x * def + \epsilon_{xi}\\
30    y_{i} = \mu_{y} + \beta_y * def + \epsilon_{yi}
31    \end{eqnarray*}
32
33 where :math:`def` is the definition variable and the residual sources of variance, :math:`\epsilon_{xi}` and :math:`\epsilon_{yi}` covary to the extent :math:`\rho`.  So, the task is to estimate: the two means :math:`\mu_{x}` and :math:`\mu_{y}`; the deviations from these means due to belonging to the group identified by having :math:`def` set to 1 (as opposed to zero), :math:`\beta_{x}` and :math:`\beta_{y}`; and the parameters of the variance covariance matrix: cov(:math:`\epsilon_{x},\epsilon_{y}`) = :math:`\rho`.
34
35 Our task is to implement the model shown in the figure below:
36
37 .. image:: graph/DefinitionMeansModel.png
38     :height: 2in
39
40
41 Data Simulation
42 ^^^^^^^^^^^^^^^
43
44 Our first step to running this model is to simulate the data to be analyzed. Each individual is measured on two observed variables, *x* and *y*, and a third variable *def* which denotes their group membership with a 1 or a 0.  These values for group membership are not accidental, and must be adhered to in order to obtain readily interpretable results.  Other values such as 1 and 2 would yield the same model fit, but would make the interpretation more difficult.  
45
46 .. code-block:: r
47
48     library(MASS)  # to get hold of mvrnorm function 
49
50     set.seed(200)  # to make the simulation repeatable
51     N=500          # sample size, per group
52
53     Sigma <- matrix(c(1,.5,.5,1),2,2)
54     group1<-mvrnorm(N, c(1,2), Sigma)
55     group2<-mvrnorm(N, c(0,0), Sigma)
56
57 We make use of the superb R function ``mvrnorm`` in order to simulate N=500 records of data for each group.  These observations correlate .5 and have a variance of 1, per the matrix Sigma.  The means of *x* and *y* in group 1 are 1.0 and 2.0, respectively; those in group 2 are both zero.  The output of the ``mvrnorm`` function calls are matrices with 500 rows and 3 columns, which are stored in group 1 and group 2.  Now we create the definition variable
58
59 .. code-block:: r
60
61     # Put the two groups together, create a definition variable, 
62     # and make a list of which variables are to be analyzed (selVars)
63     xy<-rbind(group1,group2)
64     dimnames(xy)[2]<-list(c("x","y"))
65     def<-rep(c(1,0),each=N)
66     selVars<-c("x","y")
67
68 The objects ``xy`` and ``def`` might be combined in a data frame.  However, in this case we won't bother to do it externally, and simply paste them together in the ``mxData`` function call.
69
70 Model Specification
71 ^^^^^^^^^^^^^^^^^^^
72
73 The following code contains all of the components of our model. Before running a model, the OpenMx library must be loaded into R using either the ``require()`` or ``library()`` function. This code uses the ``mxModel`` function to create an ``mxModel`` object, which we'll then run.  Note that all the objects required for estimation (data, matrices, and an objective function) are declared within the ``mxModel`` function.  This type of code structure is recommended for OpenMx scripts generally.
74
75 .. code-block:: r
76
77     defMeansModel <- mxModel("Definition Means Matrix Specification",
78         mxFitFunctionML(),
79         mxExpectationNormal(
80             covariance="Sigma",
81             means="Mu",
82             dimnames=selVars
83         ),
84
85 The first argument in an ``mxModel`` function has a special purpose. If an object or variable containing an ``MxModel`` object is placed here, then ``mxModel`` adds to or removes pieces from that model. If a character string (as indicated by double quotes) is placed first, then that becomes the name of the model. Models may also be named by including a ``name`` argument. This model is named ``"Definition Means Matrix Specification"``.
86
87 The second argument in this ``mxModel`` call is itself a function. It declares that the fit function to be optimized is maximum likelihood (ML), which is tagged ``mxFitFunctionML``.  Full information maximum likelihood (FIML) is used whenever the data allow, and does not need to be requested specifically.  The third argument in this ``mxModel`` is another function.  It declares the expectation function to be a normal distribution, ``mxExpectationNormal``.  This means the model is of a normal distribution with a particular mean and covariance.  Hence, there are in turn two arguments to this function: the covariance matrix ``Sigma`` and the mean vector ``Mu``.  These matrices will be defined later in the ``mxModel`` function call.
88
89 Model specification is carried out using ``mxMatrix`` functions to create matrices for the model. In the present case, we need four matrices.  First is the predicted covariance matrix, ``Sigma``.  Next, we use three matrices to specify the model for the means.  First is ``M`` which corresponds to estimates of the means for individuals with definition variables with values of zero.  Individuals with definition variable values of 1 will have the value in ``M`` plus the value in the matrix ``beta``.  So both matrices are of size 1x2 and both contain two free parameters.  There is a separate deviation for each of the variables, which will be estimated in the elements 1,1 and 1,2 of the ``beta`` matrix.  Last, but by no means least, is the matrix ``def`` which contains the definition variable.  The variable *def* in the ``mxData`` data frame is referred to in the matrix label as ``data.def``.  In the present case, the definition variable contains a 1 for group 1, and a zero otherwise.  
90
91 .. code-block:: r
92
93     # covariance matrix
94     mxMatrix(
95         type="Symm", 
96         nrow=2, 
97         ncol=2, 
98         free=TRUE, 
99         values=c(1, 0, 1), 
100         name="Sigma"
101     ),
102     # means
103     mxMatrix(
104         type="Full", 
105         nrow=1, 
106         ncol=2, 
107         free=TRUE, 
108         name="M"
109     ),
110     # regression coefficient
111     mxMatrix(
112         type="Full", 
113         nrow=1, 
114         ncol=2, 
115         free=TRUE, 
116         values=c(0, 0),
117         name="beta"
118     ),
119     # definition variable
120     mxMatrix(
121         type="Full", 
122         nrow=1, 
123         ncol=2, 
124         free=FALSE, 
125         labels="data.def",
126         name="def"
127     ),
128
129 The trick - commonly used in regression models - is to multiply the ``beta`` matrix by the ``def`` matrix.  This multiplication is effected using an ``mxAlgebra`` function call:
130
131 .. code-block:: r
132
133    mxAlgebra(
134         expression= M+beta*def, 
135         name="Mu"
136     ),
137
138 The result of this algebra is named ``Mu``, and this handle is referred to in the ``mxExpectationNormal`` function call.  
139
140 Next, we declare where the data are, and their type, by creating an ``MxData`` object with the ``mxData`` function.  This piece of code creates an ``MxData`` object. It first references the object where our data are, then uses the ``type`` argument to specify that this is raw data. Because the data are raw and the fit function is ``mxFitFunctionML``, full information maximum likelihood is used in this ``mxModel``.  Analyses using definition variables have to use raw data, so that the model can be specified on an individual data vector level.
141
142 .. code-block:: r
143
144     mxData(
145          observed=data.frame(xy,def), 
146          type="raw"
147     ))
148
149 We can then run the model and examine the output with a few simple commands.
150
151 Model Fitting
152 ^^^^^^^^^^^^^^
153
154 .. code-block:: r
155
156     # Run the model
157     defMeansFit <- mxRun(defMeansModel)
158     defMeansFit@matrices
159     defMeansFit@algebras
160
161 It is possible to compare the estimates from this model to some summary statistics computed from the data:
162
163 .. code-block:: r
164
165     # Compare OpenMx estimates to summary statistics computed from raw data.
166     # Note that to calculate the common variance, 
167     # group 1 has 1 and 2 subtracted from every Xi and Yi in the sample data,
168     # so as to estimate variance of combined sample without the mean correction.
169  
170     # First compute some summary statistics from data
171     ObsCovs<-cov(rbind(group1 - rep(c(1,2),each=N), group2))
172     ObsMeansGroup1<-c(mean(group1[,1]), mean(group1[,2]))
173     ObsMeansGroup2<-c(mean(group2[,1]), mean(group2[,2]))
174  
175     # Second extract parameter estimates and matrix algebra results from model
176     Sigma <- mxEval(Sigma, defMeansFit)
177     Mu <- mxEval(Mu, defMeansFit)
178     M <- mxEval(M, defMeansFit)
179     beta <- mxEval(beta, defMeansFit)
180  
181     # Third, check to see if things are more or less equal
182     omxCheckCloseEnough(ObsCovs,Sigma,.01)
183     omxCheckCloseEnough(ObsMeansGroup1,as.vector(M+beta),.001)
184     omxCheckCloseEnough(ObsMeansGroup2,as.vector(M),.001)
185
186 These models may also be specified using paths instead of matrices. See :ref:`definitionmeans-path-specification` for path specification of these models.