Wednesday, February 25, 2026

Programming an estimation command in Stata: Mata 101


I introduce Mata, the matrix programming language that’s a part of Stata.

That is the eleventh submit within the collection Programming an estimation command in Stata. I like to recommend that you just begin at first. See Programming an estimation command in Stata: A map to posted entries for a map to all of the posts on this collection.

Assembly Mata

Mata is a matrix programming language that’s a part of Stata. Mata code is quick as a result of it’s compiled to object code that runs on a digital machine; kind assist m1_how for particulars.

The best approach to study Mata is to make use of it. I start with an interactive session. (You may discover it helpful to kind alongside.)

Instance 1: A primary interactive Mata session


. mata:
------------------------------------------------- mata (kind finish to exit) ------
: X = J(3, 4, 5)

: X
       1   2   3   4
    +-----------------+
  1 |  5   5   5   5  |
  2 |  5   5   5   5  |
  3 |  5   5   5   5  |
    +-----------------+

: w = (1::4)

: w
       1
    +-----+
  1 |  1  |
  2 |  2  |
  3 |  3  |
  4 |  4  |
    +-----+

: v = X*w

: v
        1
    +------+
  1 |  50  |
  2 |  50  |
  3 |  50  |
    +------+

: v'
        1    2    3
    +----------------+
  1 |  50   50   50  |
    +----------------+

: finish
--------------------------------------------------------------------------------

Typing mata: causes Stata to drop right down to a Mata session. Typing finish ends the Mata session, thereby popping again as much as Stata. The dot immediate . is Stata asking for one thing to do. After you kind mata:, the colon immediate : is the Mata compiler asking for one thing to do.

Typing X = J(3, 4, 5) on the colon immediate causes Mata to compile and execute this code. J(r, c, v) is the Mata perform that creates an r(occasions)c matrix, every of whose parts is v. The expression on the right-hand aspect of the project operator = is assigned to the image on the left-hand aspect.

Typing X by itself causes Mata to show what X incorporates, which is a 3(occasions)4 matrix of 5s. Unassigned expressions show their outcomes. Sort assist m2_exp for particulars about expressions.

Typing w = (1::4) causes Mata to make use of the column vary operator to create the 4(occasions)1 column vector that was assigned to w and displayed after I typed w by itself. Sort assist m2_op_range for particulars and a dialogue of the row vary operator.

Typing v = X*w causes Mata to assign the matrix product of X occasions w to v, which I subsequently show. I then illustrate that ‘ is the transpose operator. Sort assist m2_exp, marker(remarks7) for a listing of operators.

Once more, typing finish ends the Mata session.

In nearly all of the work I do, I extract submatrices from a matrix.

Instance 2: Extracting submatrices from a matrix


. mata:
------------------------------------------------- mata (kind finish to exit) ------
: rseed(1234)

: W = runiform(4,4)

: W
                 1             2             3             4
    +---------------------------------------------------------+
  1 |  .9472316166   .0522233748   .9743182755   .9457483679  |
  2 |  .1856478315   .9487333737   .8825376215   .9440776079  |
  3 |  .0894258515   .7505444902   .9484983174   .1121626508  |
  4 |  .4809064012   .9763447517   .1254975307   .7655025515  |
    +---------------------------------------------------------+

: v = (2, 4)

: u = (1 3)

: v
       1   2
    +---------+
  1 |  2   4  |
    +---------+

: u
       1
    +-----+
  1 |  1  |
  2 |  3  |
    +-----+

: W[u, v]
                 1             2
    +-----------------------------+
  1 |  .0522233748   .9457483679  |
  2 |  .7505444902   .1121626508  |
    +-----------------------------+

: W[| 1,1  3,3 |]
                 1             2             3
    +-------------------------------------------+
  1 |  .9472316166   .0522233748   .9743182755  |
  2 |  .1856478315   .9487333737   .8825376215  |
  3 |  .0894258515   .7505444902   .9484983174  |
    +-------------------------------------------+

: finish
--------------------------------------------------------------------------------

I take advantage of rseed() to set the seed for the random-number generator after which use runiform(r,c) to create a 4(occasions)4 matrix uniform deviates, which I subsequently show.

Subsequent, I take advantage of the row-join operator , to create the row vector v and I take advantage of the column-join operator to create the column vector u. Sort assist m2_op_join for particulars.

Typing W[u,v] extracts from W the rows specified within the vector u and the columns specified within the vector v.

I regularly extract rectangular blocks outlined by a top-left factor and a bottom-right factor. I illustrate this syntax by typing

W[| 1,1 3,3 |]

Intimately, [| opens a range-subscript extraction, 1,1 is the address of the top-left element, separates the top-left element from the bottom-right element, 3,3 is the address of the bottom-right element, and |] closes a range-subscript extraction. Sort assist m2_subscripts for particulars.

Mockingly, when I’m doing matrix programming, I regularly need the element-by-element operator as an alternative of the matrix operator. Preface any matrix operator in Mata with a colon (:) to acquire the element-by-element equal.

Instance 3: Aspect-wise operators


. mata:
------------------------------------------------- mata (kind finish to exit) ------
: W = W[| 2,1  4,4 |]

: W
                 1             2             3             4
    +---------------------------------------------------------+
  1 |  .1856478315   .9487333737   .8825376215   .9440776079  |
  2 |  .0894258515   .7505444902   .9484983174   .1121626508  |
  3 |  .4809064012   .9763447517   .1254975307   .7655025515  |
    +---------------------------------------------------------+

: v = .1*(4::6)

: v
        1
    +------+
  1 |  .4  |
  2 |  .5  |
  3 |  .6  |
    +------+

: v:*W
                 1             2             3             4
    +---------------------------------------------------------+
  1 |  .0742591326   .3794933495   .3530150486   .3776310432  |
  2 |  .0447129257   .3752722451   .4742491587   .0560813254  |
  3 |  .2885438407    .585806851   .0752985184   .4593015309  |
    +---------------------------------------------------------+

: v'*W
                 1             2             3             4
    +---------------------------------------------------------+
  1 |  .4075158991   1.340572446   .9025627257   .8930138994  |
    +---------------------------------------------------------+

: finish
--------------------------------------------------------------------------------

I extract the underside 4 rows of W, retailer this matrix in W, and show this new W. I then create a row-wise conformable vector v, carry out element-wise multiplication of v throughout the columns of W, and show the outcome. I can not kind v*W as a result of the three(occasions)1 v shouldn’t be conformable with the three(occasions)3 W. However I can, and do, kind v’*W as a result of the 1(occasions)3 v’ is conformable with the three(occasions)3 W.

Instance 4 makes use of an element-wise logical operator.

Instance 4: Aspect-wise logical operator


. mata:
------------------------------------------------- mata (kind finish to exit) ------
: W :< v
       1   2   3   4
    +-----------------+
  1 |  1   0   0   0  |
  2 |  1   0   0   1  |
  3 |  1   0   1   0  |
    +-----------------+

: finish
--------------------------------------------------------------------------------

I show the results of evaluating the element-wise conformable v with W. Sort assist m2_op_colon for particulars.

Stata knowledge in Mata

The Mata perform st_data() creates a Mata matrix containing a duplicate of the information from the Stata dataset in reminiscence. The Mata perform st_view() creates a Mata view of the information within the Stata dataset in reminiscence. Views act like matrices, however there’s a speed-space tradeoff. Copies are quick at the price of utilizing twice as a lot reminiscence. Views are slower, however they use little further reminiscence.

Copying the information from Stata into Mata doubles the reminiscence used, however the values are saved in Mata reminiscence. Each time a Mata perform asks for a worth from a matrix, it finds it instantly. In distinction, a view of the information in Stata barely will increase the reminiscence used, however the values are in Stata reminiscence. Each time a Mata perform asks for a worth from a view, it finds an indication telling it the place in Stata to get the worth.

Instance 5: Information from Stata into Mata


. sysuse auto
(1978 Vehicle Information)

. record mpg headroom trunk rep78 flip overseas in 1/3 , nolabel

     +-------------------------------------------------+
     | mpg   headroom   trunk   rep78   flip   overseas |
     |-------------------------------------------------|
  1. |  22        2.5      11       3     40         0 |
  2. |  17        3.0      11       3     40         0 |
  3. |  22        3.0      12       .     35         0 |
     +-------------------------------------------------+

. mata:
------------------------------------------------- mata (kind finish to exit) ------
: Y = st_data(., "mpg headroom trunk")

: st_view(X=., ., "rep78 flip overseas")

: V = Y,X

: V[| 1,1  3,6 |]
         1     2     3     4     5     6
    +-------------------------------------+
  1 |   22   2.5    11     3    40     0  |
  2 |   17     3    11     3    40     0  |
  3 |   22     3    12     .    35     0  |
    +-------------------------------------+

: X[3,1] = 7

: X[| 1,1  3,3 |]
        1    2    3
    +----------------+
  1 |   3   40    0  |
  2 |   3   40    0  |
  3 |   7   35    0  |
    +----------------+

: finish
--------------------------------------------------------------------------------

. record rep78 flip overseas in 1/3 , nolabel

     +------------------------+
     | rep78   flip   overseas |
     |------------------------|
  1. |     3     40         0 |
  2. |     3     40         0 |
  3. |     7     35         0 |
     +------------------------+

After I record out the primary three observations on six variables within the auto dataset, I drop right down to Mata, use st_data() to place a duplicate of all of the observations on mpg, headroom, and trunk into the Mata matrix Y, and use st_view() to create the Mata view X on to all of the observations on rep78, flip, and overseas.

After row-joining Y and X to create V, I show the primary 3 rows of V. Be aware that the third remark on rep78 is lacking and that Mata matrices and views can include lacking values.

Altering the worth of a component in a view modifications the information in Stata. I illustrate this level by changing the (3,1) factor of the view X with 7, displaying the primary three rows of the view, and itemizing out the primary three observations on rep78, flip, and overseas.

Copying matrices between Mata and Stata

The Mata perform st_matrix() places a duplicate of a Stata matrix right into a Mata matrix, or it places a duplicate of a Mata matrix right into a Stata matrix. In instance 6, V = st_matrix(“B”) places a duplicate of the Stata matrix B into the Mata matrix V.

Instance 6: Creating a duplicate of a Stata matrix in a Mata vector


. matrix B = (1, 2 3, 4)

. matrix record B

B[2,2]
    c1  c2
r1   1   2
r2   3   4

. mata:
------------------------------------------------- mata (kind finish to exit) ------
: V = st_matrix("B")

: V
       1   2
    +---------+
  1 |  1   2  |
  2 |  3   4  |
    +---------+

: finish
--------------------------------------------------------------------------------

In instance 7, st_matrix(“Z”, W) places a duplicate of the Mata matrix W into the Stata matrix Z.

Instance 7: Creating a duplicate of a Mata matrix in a Stata vector


. mata:
------------------------------------------------- mata (kind finish to exit) ------
: W = (4..67..9)

: W
       1   2   3
    +-------------+
  1 |  4   5   6  |
  2 |  7   8   9  |
    +-------------+

: st_matrix("Z", W)

: finish
--------------------------------------------------------------------------------

. matrix record Z

Z[2,3]
    c1  c2  c3
r1   4   5   6
r2   7   8   9

Strings

Mata matrices may be string matrices.

In my work, I regularly have a listing of variables in a string scalar that’s simpler to work with as a string vector.

Turning a string scalar record right into a string vector


. mata:
------------------------------------------------- mata (kind finish to exit) ------
: s1 = "value mpg trunk"

: s1
  value mpg trunk

: s2 = tokens(s1)

: s2
           1       2       3
    +-------------------------+
  1 |  value     mpg   trunk  |
    +-------------------------+

: finish
--------------------------------------------------------------------------------

I take advantage of tokens() to create the string vector s2 from the string vector s1.

Stream of management

Mata has constructs for looping over a block of code enclosed between curly braces or solely executing it if an expression is true.

I regularly use the for() development to loop over a block of code.

Code block 1: for()


mata:
for(i=1; i<=3; i=i+1) {
	i
}
finish

On this instance, I set i to the preliminary worth of 1. The loop will proceed so long as i is lower than or equal to three. Every time by the loop, the block of code enclosed between the curly braces is executed, and 1 is added to the present worth of i. The code block shows the worth of i. Instance 9 illustrates these factors.

Instance 9: A for loop


. mata:
------------------------------------------------- mata (kind finish to exit) ------
: for(i=1; i<=3; i=i+1) {
>         i
> }
  1
  2
  3

: finish
--------------------------------------------------------------------------------

Typically, I need to execute a block of code so long as a situation is true, through which case I take advantage of a whereas loop, as in code block 2 and instance 10.

Code block 1: globala.do


i = 7
whereas (i>5) {
    i
    i = i - 1
}

I set i to 7 and repeat the block of code between the curly braces whereas i is bigger than 5. The block of code shows the present worth of i, then subtracts 1 from i.

Instance 10: Some time loop


. mata:
------------------------------------------------- mata (kind finish to exit) ------
: i = 7

: whereas (i>5) {
>     i
>     i = i - 1
> }
  7
  6

: finish
--------------------------------------------------------------------------------

The if assemble solely executes a code block if an expression is true. I often use the if-else assemble that executes one code block if an expression is true and one other code block if the expression is fake.

Instance 11: An if-else assemble


. mata:
-------------------------------------------- mata (kind finish to exit) ---
: for(i=2; i<10; i=i+5) {
>         i
>         if (i<3) {
>                 "i is lower than 3"
>         }
>         else {
>                 "i shouldn't be lower than 3"
>         }
> }
  2
  i is lower than 3
  7
  i shouldn't be lower than 3

: finish
-------------------------------------------------------------------------

One-line calls to Mata

I regularly make one-line calls to Mata from Stata. A one-line name to Mata causes Stata to drop to Mata, compile and execute the road of Mata code, and pop again as much as Stata.

Instance 12: One-line calls to Mata


. mata: st_matrix("Q", I(3))

. matrix record Q

symmetric Q[3,3]
    c1  c2  c3
r1   1
r2   0   1
r3   0   0   1

In instance 12, I take advantage of the one-line name to Mata mata: st_matrix(“Q”, I(3)) to place a duplicate of the Mata matrix returned by the Mata expression I(3) into the Stata matrix Q. After the one-line name to Mata, I’m again in Stata, so I take advantage of matrix record Q to point out that the Stata matrix Q is a duplicate of the Mata matrix W.

Achieved and undone

I used an interactive session to introduce Mata, the matrix programming language that’s a part of Stata.

Within the subsequent submit, I present find out how to outline Mata features.



Related Articles

Latest Articles