Intro Mata
Intro Mata
Intro Mata
Introduction to Mata
Since the release of version 9, Stata contains a full-fledged matrix
programming language, Mata, with most of the capabilities of MATLAB,
R, Ox or GAUSS. You can use Mata interactively, or you can develop
Mata functions to be called from Stata. In this talk, we emphasize the
latter use of Mata.
Mata functions may be particularly useful where the algorithm you wish
to implement already exists in matrix-language form. It is quite
straightforward to translate the logic of other matrix languages into
Mata: much more so than converting it into Statas matrix language.
A large library of mathematical and matrix functions is provided in
Mata, including optimization routines, equation solvers,
decompositions, eigensystem routines and probability density
functions. Mata functions can access Statas variables and can work
with virtual matrices (views) of a subset of the data in memory. Mata
also supports file input/output.
Christopher F Baum (BC / DIW)
133 / 207
Introduction to Mata
134 / 207
Introduction to Mata
135 / 207
Introduction to Mata
Speed advantages
Speed advantages
Last but by no means least, ado-file code written in the matrix
language with explicit subscript references is slow. Even if such a
routine avoids explicit subscripting, its performance may be
unacceptable. For instance, David Roodmans xtabond2 can run in
version 7 or 8 without Mata, or in version 9 or 10 with Mata. The
non-Mata version is an order of magnitude slower when applied to
reasonably sized estimation problems.
In contrast, Mata code is automatically compiled into bytecode, like
Java, and can be stored in object form or included in-line in a Stata
do-file or ado-file. Mata code runs many times faster than the
interpreted ado-file language, providing significant speed
enhancements to many computationally burdensome tasks.
136 / 207
Introduction to Mata
137 / 207
138 / 207
Operators
Operators
To understand Mata syntax, you must be familiar with its operators.
The comma is the column-join operator, so
: r1 = ( 1, 2, 3 )
creates a three-element row vector. We could also construct this
vector using the row range operator (..) as
: r1 = (1..3)
The backslash is the row-join operator, so
c1 = ( 4 \ 5 \ 6 )
creates a three-element column vector. We could also construct this
vector using the column range operator (::) as
: c1 = (4::6)
Christopher F Baum (BC / DIW)
139 / 207
Operators
140 / 207
Operators
141 / 207
Operators
142 / 207
143 / 207
=
=
=
=
( 1, 2, 3 )
( 1, 2, 3 \ 4, 5, 6 \ 7, 8, 9 )
r4 :+ m2
m1 :/ r1
adds the row vector r4 to each row of the 3 3 matrix m2 to form m3,
and divides the elements of each row of matrix m1 by the
corresponding elements of row vector r1 to form m4.
Matas scalar functions will also operate on elements of matrices:
d = sqrt(c)
will take the element-by-element square root, returning missing values
where appropriate.
Christopher F Baum (BC / DIW)
144 / 207
Logical operators
Logical operators
As in Stata, the equality logical operators are a == b and a != b.
They will work whether or not a and b are conformable or even of the
same type: a could be a vector and b a matrix. They return 0 or 1.
Unary not ! returns 1 if a scalar equals zero, 0 otherwise, and may be
applied in a vector or matrix context, returning a vector or matrix
of 0, 1.
The remaining logical comparison operators (>, >=, <, <=) can
only be used on objects that are conformable and of the same general
type (numeric or string). They return 0 or 1.
As in Stata, the logical and (&) and or (|) operators may only be
applied to real scalars.
Christopher F Baum (BC / DIW)
145 / 207
Subscripting
Subscripting
Subscripts in Mata utilize square brackets, and may appear on either
the left or right of an algebraic expression. There are two forms: list
subscripts and range subscripts.
With list subscripts, you can reference a single element of an array as
x[i,j]. But i or j can also be a vector: x[i,jvec], where jvec=
(4,6,8) references row i and those three columns of x. Missing
values (dots) reference all rows or columns, so x[i,.] or x[i,]
extracts row i, and x[.,.] or x[,] references the whole matrix.
You may also use range operators to avoid listing each consecutive
element: x[(1..4),.] and x[(1::4),.] both reference the first
four rows of x. The double-dot range creates a row vector, while the
double-colon range creates a column vector. Either may be used in a
subscript expression. Ranges may also decrement, so x[(3::1),.]
returns those rows in reverse order.
Christopher F Baum (BC / DIW)
146 / 207
Subscripting
Range subscripts use the notation [| |]. They can reference single
elements of matrices, but are not useful for that. More useful is the
ability to say x[| i,j \ m,n |], which creates a submatrix starting
at x[i,j] and ending at x[m,n]. The arguments may be specified as
missing (dot), so x[| 1,2 \4,. |] specifies the submatrix ending in
the last column and x[| 2,2 \ .,.|] discards the first row and
column of x. They also may be used on the left hand side of an
expression, or to extract a submatrix:
v = invsym(xx)[| 2,2 \ .,.|] discards the first row and
column of the inverse of xx.
You need not use range subscripts, as even the specification of a
submatrix can be handled with list subscripts and range operators, but
they are more convenient for submatrix extraction and faster in terms
of execution time.
147 / 207
Loop constructs
Loop constructs
Several constructs support loops in Mata. As in any matrix language,
explicit loops should not be used where matrix operations can be used.
The most common loop construct resembles that of the C language:
for (starting_value; ending_value; incr ) {
statements
}
where the three elements define the starting value, ending value or
bound and increment or decrement of the loop. For instance:
for (i=1; i<=10; i++) {
printf("i=%g \n", i)
}
prints the integers 1 to 10 on separate lines.
If a single statement is to be executed, it may appear on the for
statement.
Christopher F Baum (BC / DIW)
148 / 207
Loop constructs
149 / 207
150 / 207
dof = n-1
dof = n-k
can be written as
dof = ( k==0 ? n-1 : n-k )
The increment (++) and decrement () operators can be used to
manage counter variables. They may precede or follow the variable.
The operator A # B produces the Kronecker or direct product of A and
B.
151 / 207
152 / 207
153 / 207
154 / 207
Data access
Data access
155 / 207
st_view( )
st_view( )
One of the most useful Mata concepts is the view matrix, which as its
name implies is a view of some of Statas variables for specified
observations, created by a call to st_view(). Unlike most Mata
functions, st_view() does not return a result. It requires three
arguments: the name of the view matrix to be created, the
observations (rows) that it is to contain, and the variables (columns).
An optional fourth argument can specify touse: an indicator variable
specifying whether each observation is to be included.
st_view(x, ., varname, touse)
States that the previously-declared Mata vector x should be created
from all the observations (specified by the missing second argument)
of varname, as modified by the contents of touse. In the Stata code,
the marksample command imposes any if or in conditions by
setting the indicator variable touse.
Christopher F Baum (BC / DIW)
156 / 207
st_view( )
157 / 207
st_view( )
158 / 207
st_data( )
st_data( )
An alternative to view matrices is provided by st_data() and
st_sdata(), which copy data from Stata variables into Mata
matrices, vectors or scalars:
X = st_data(., .)
places a copy of all variables in Statas memory into matrix X.
However, this operation requires at least twice as much memory as
consumed by the Stata variables, as Mata does not have Statas full
set of 1-, 2-, and 4-byte data types. Thus, although a view matrix can
reference any variables currently in Statas memory with minimal
overhead, a matrix created by st_data() will consume considerable
memory, just as a matrix in Statas own matrix language does.
Similar to st_view(), an optional third argument to st_data() can
mark out desired observations.
Christopher F Baum (BC / DIW)
159 / 207
160 / 207
A Mata function may take one (or several) existing variables and create
a transformed variable (or set of variables). To do that with views,
create the new variable(s), pass the name(s) as a newvarlist and set
up a view matrix.
st_view(Z=., ., tokens(newvarlist), touse)
Then compute the new content as:
Z[., .] = result of computation
It is very important to use the [., .] construct as shown. Z = will
cause a new matrix to be created and break the link to the view.
161 / 207
You may also create new variables and fill in their contents by
combining these techniques:
st_view(Z, ., st_addvar(("int", "float"), ///
("idnr", "bp")))
Z[., .] = result of computation
In this example, we create two new Stata variables, of data type int
and float, respectively, named idnr and bp.
You may also use subviews and, for panel data, panelsubviews. We
will not discuss those here.
162 / 207
163 / 207
164 / 207
165 / 207
166 / 207
version 11
mata:
void m_mysum(string scalar vname,
string scalar touse)
st_view(X, ., vname, touse)
mu = mean(X)
st_numscalar("N", rows(X))
st_numscalar("mu", mu)
st_numscalar("sum" ,rows(X) * mu)
st_numscalar("sigma", sqrt(variance(X)))
end
167 / 207
168 / 207
169 / 207
170 / 207
The Mata code as shown is strict: all objects must be defined. The
function is declared void as it does not return a result. A Mata
function could return a single result to Mata, but we need to send two
results back to Stata. The input arguments are declared as string
scalar as they are variable names.
We create a view matrix, colvector x, as the subset of varname for
which touse==1. Matas colminmax() function computes the
extrema of its arguments as a two-element vector, and
st_numscalar() returns each of them to Stata as r(min),
r(max) respectively.
171 / 207