3 Mata

3.1 ¿Qué es Mata?

Esta introducción esta basada en la guía de Asjad Naqvi.

  • Mata es un lenguaje de programación matricial.
  • Es más rápido que Stata, pero necesita más precisión (ej. dimensiones de las matrices).
  • Muchos de los operadores de Mata son similares a R o Matlab. Adicionalmente, incluye sus propios optimizadores y funciones útiles.
  • Esta sección será una pequeña introducción al lenguaje. Tiene como objetivo mostrarles el abanico de herramientas que Mata posee con el fin de que puedan utilizarlo para hacer sus propios programas.

La sintaxis básica de Mata

* Opción 1 
mata 

< comando de mata 1 > 
< comando de mata 2 >
< y así .... > 
end 

* Opción 2 
mata <un comando de mata>
 
* Opción 3 : la versión estricta
mata: <un comando de mata> 
  

Si son utilizados dos puntos y ocurre un error, Mata será abortado, volverá a Stata y aparecerá un mensaje de error.

* Ejemplo 1
mata 
emat = 7 + 3
emat 
end

* Ejemplo 2
mata 
emat = ("Josefa", "Perez")
emat = (21\8)
mmat = (17\6)
vmat = (25,3\3,11)
emat, mmat, vmat 
end

Para buscar ayuda, podemos hacer:

* Ejemplo 1
help mata comando
help mata cholesky()

Comandos básicos:Al igual que Stata, Mata posee sus propios comandos. Algunos útiles de recordar son:

mata describe 
mata clear 
mata rename nombre
mata drop nombre1 nombre2
mata stata

* Ejemplo
mata 
mata clear 
emat = ("Josefa", "Perez")
emat = (21\8)
mmat = (17\6)
vmat = (25,3\3,11)
mata describe 
emat, mmat, vmat
mata rename vmat vmat_renombrada
mata drop mmat
emat, vmat_renombrada
end

Para hacer comentarios en Mata hay que utilizar //. No funcionan los asteriscos como en Stata. Todo los que se genera en Mata queda en la memoria a menos que Stata se cierre, se use clear allen Stata o bien mata: mata clear. Todas las matrices y funciones definidas se mantienen en el espacio de trabajo de Mata espacio de trabajo cuando se termina mata y se puede acceder a ellas cuando se vuelve a entrar en mata.

3.1.0.1 Matrices

Una forma común de generar una matriz en Mata es importándola desde los datos de Stata.

mata: X = st_data(.,("var1", "var2"))

Definimos la matriz X, que tiene todas las observaciones (filas) y dos columnas var1 y var2. st_ permite a Mata interactuar con la interfaz de Stata con el fin de pasar información de un lado a otro. Revisar help m4_stata.

* Ejemplo 4: confeccionar matrices en base a mata
sysuse auto.dta
mata
mata clear 
mata: X = st_data(.,("price", "mpg"))
X
mata describe
end 

Otra opción es definir matrices dentro de Mata.

mata A = (1,2 \ 3,4)

Definimos la matriz A, la cual podemos ver escribiendo mata A. Veremos una matriz cuadrada de 2x2. Notar que la coma separa elementos entre columnas mientras que el slash mueve elementos entre filas. El uso de paréntesis es opcional en Mata, pero es más conveniente y es una buena práctica de estilo utilizarlos. También se pueden definir matrices especiales.

* Vector fila o Vector columna
mata 1,2,3
mata 1\2\3

* Vector fila o Vector columna del 1 al 4
mata 1..4
mata 1::4

Finalmente, uno puede generar matrices similar a lo que se hace en Stata.

mata J(2,2,1)

Este comando genera una matriz de 2x2 rellena de unos. La sintaxis genérica es: mata J(filas, columnas, constante). Para definir una matriz identidad: mata I(5).

Otro operador útil es range:

mata range(1,7,2)

Crea un vector que empieza en 1 y termina en 7 saltándose de 2 en 2 (es decir, (1,3,5,7)). Si quiero generar una matriz con números aleatorios provenientes de una distribución uniforme (0,1) : mata runiform(3,3).

Accediendo a los elementos de una matriz

  • Podemos acceder a los elementos de una matriz.
    • mata A[1,2]: fila 1, columna 2.
    • mata A[1,.]: Todas las columnas de la fila 1.
    • mata A[.,2]: Todas las filas de la columna 2.
  • También podemos extraer sub-conjuntos de elementos:
* Empezar de fila 2 columna 1 hasta fila 3 columna 3
mata A[|2,1\3,3|]       
* Tomar filas 2 y 3 y columnas de la 1 a la 3.
mata A[(2::3),(1..3)]   

Pegando elementos de matrices:

mata
A = runiform(1,2)
B = runiform(1,2)

* Opción 1 : pegar horizontalmente
A,B   
* Opción 2 : pegar verticalmente
A\B   
end

A,B las pega horizontalmente, es decir por columnas (filas son las mismas). A\B las pega vertical, es decir por filas (columnas son las mismas).

Operaciones básicas entre matrices y por elementos: Una vez definidas las matrices, también se dedica bastante tiempo a sumar, restar, multiplicar y dividir matrices entre sí. Vamos a ver algunas operaciones entre matrices y también entre elementos.

mata
 A = (1,2,3\4,5,6)
 B = (2,3\4,5\6,7)
 A * B
end

A * B es una operación entre matrices, de forma tal que el número de filas de A debe ser igual al número de columnas de B. Si queremos que cada elemento de A sea multiplicado por el mismo elemento en B, es necesario trasponer alguna matriz y cambiar el operador.

mata
 A = (1,2,3\4,5,6)
 B = (2,3\4,5\6,7)
  A' :* B
  A  :* B'
end

En el primer caso la matriz resultante corresponde a una matriz de 3x2, en el segundo caso es una matriz de 2x3.

Operadores lógicos y funciones sobre escalares: Las matrices también pueden ser comparadas a través de operadores lógicos. A == B chequea si dos matrices son iguales. Esto también puede hacerse elemento por elemento (por ejemplo A:>=B). Tambien se puede utilizar !=.

Mata también tiene funciones sobre escalares:

mata
  X = (-2, 1 \ 0, 5)
  abs(X)   // valor absoluto de cada elemento
  sign(X)  // signo de cada elemento
  exp(X)   // exponencial de cada elemento
  sqrt(X)  // raíz cuadrada de cada elemento
  sin(X)   // seno de cada elemento
end

Algunas funciones para operar en matrices son:

mata
A = (5,4\6,7)
B = (1,6\3,2)
end

* Número de filas y columnas 
mata rows(A)
mata cols(A)

* Suma de las filas/columnas
mata rowsum(B)
mata colsum(B)

* Calcular el promedio (retorna un vector fila)
mata mean(B')' 

* Seleccionar todas las columnas sin ceros
mata D = (1,0,2,3,0)
mata selectindex(D) 

* Select para condiciones más flexibles
select(B, B[.,1]:>2)

* Ordenar matrices 
mata sort(B,2)  // Ordena según la columna 2 de B
mata jumble(B) // Aleatoriza las filas de B

Mata contiene varias funciones para extraer propiedades de las matrices:

mata
A = (5,4\6,7)
det(A)         // Determinante de A
invsym(A)      // Ibversa de A
trace(A)       // Traza de A
rank(A)        // Rango de A
norm(A)        // Norma de A
X=.            // Vectores propios
L=.            // Valores propios
end

Mata contiene varias funciones para operar o manipular dos matrices:

mata
A = (5,4\6,7)
B = (1,6\3,2)
A' * B            // A x B
cross(A,B)        // A x B using a solver (faster)
end

Al igual que Stata, Mata puede utilizar iteradores. While loop:

mata
  x = 1                  // Valor inicial
  X = 4                  // Valor final
  while (x <= X) {       // Iniciar condición del while
  printf("\%g \n", x)     // Alguna operación de Mata aquí
  x++                    // Incremental
  }                      // Terminar el while
end

For Loops:

* Este for
for (expr1; expr2; expr3) {
stmts
}
* Es equivalente a 
expr1
while (expr2) {
stmt
expr3
}

Los valores iniciales y finales pueden extraerse de algunas declaraciones condicionales como las dimensiones de las matrices. Mata sólo permite incrementos de 1.

Notar que aquí es bien distinto a Stata:

mata
   N = 4                      // Valor final
   for (i=1; i<=N; i++) {     // for loop 
   printf("%g \n", i)         // some Mata operation here
   }                          // end for loop
end

If/else son:

mata
 x = 3                       // Valor de x
   
  for (i=1; i<=5; i++) {     // Empezar el loop
    if (x > i) {             // if
      printf("\%g\n", 0)      // Comando de mata si la condición se cumple
      }
    else {                   //  en caso contrario
      printf("\%g\n", 1)      // ejecutar este comando de mata
      }
  }
end

Mata también permite abreviar la sintaxis en caso de que existan dos o mas condiciones.

(a ? b : c)

“a” es la condición, “b” es el valor en caso de que sea verdadero y “c” en caso de que sea falsa. Para el ejemplo, la condición sería: (x > i ? 1 : 0).

3.1.0.2 De Stata a Mata

Estimar un MCO: Un ejemplo estándar es hacer un simple OLS en Mata.

sysuse auto, clear
mata
 y = st_data(.,"price")
 X = st_data(.,("mpg", "weight"))
 X = X, J(rows(X),1,1)
    beta   = invsym(cross(X,X))*cross(X,y)
    esq    = (y - X*beta) :^ 2
    V      = (sum(esq)/(rows(X)-cols(X)))*invsym(cross(X,X))
    stderr = sqrt(diagonal(V))
      st_matrix("b", beta)
      st_matrix("se", stderr)
end

For Loops

  • En Mata, la variable dependiente se importa como el vector y las variables independientes se importan como la matriz X. A esta matriz X se le añade un vector columna de unos para el intercepto.
  • Como el vector de unos debe tener el mismo número de filas que la matriz X, nótese el uso del operador J().
  • En el último paso, las betas y los errores estándar se exportan a Stata como matrices de Stata.

3.1.0.3 Funciones en Mata

Vector: Un ejemplo estándar es hacer un simple OLS en Mata.

* Generar un vector 
mata 
function zeros(c)
{
    a = J(c, 1, 0)
    return(a)
}
b = zeros(3)
b
end 

Matriz:

* Generar una matriz
mata 
function zerosv1(real scalar c, real scalar r)
{
real matrix A 
A = J(c,r,0)
return(A)
}
b = zerosv1(3,2)
b
end 

Hacer opcionales:

mata 
function zerosv2(real scalar c,| real scalar r)
{
real matrix A
if (args()==1) r = 1
A = J(c, r, 0)
return(A)
}
end 

mata 
zerosv2(3,2)
end

help m2 syntax

Guardar:

mata 
function zerosfinal(real scalar c,| real scalar r)
{
real matrix A
if (args()==1) r = 1
A = J(c, r, 0)
return(A)
}

mata stata cd "\$ejercicios"
mata mosave zerosfinal(), replace

end 

Dos referencias recomendadas para profundizar en Mata:

  • An Introduction to Stata Programming, Second Edition ()
  • The Mata Book: A Book for Serious Programmers and Those Who Want to Be ()