jueves, 26 de marzo de 2020

Importar datos COVID-19 de la Universidad Johns Hopkins


Chuck Huber, Director Asociado de Alcance Estadístico.

Como muchos de ustedes, estoy trabajando desde casa y revisando las últimas noticias sobre COVID-19 con frecuencia. Veo muchos números y gráficos, así que busqué los "datos oficiales". Una de las mejores fuentes de datos que he encontrado está en el sitio web de GitHub para el Centro de Ciencias e Ingeniería de Sistemas de la Escuela de Ingeniería Johns Hopkins Whiting. Los datos para cada día se almacenan en un archivo separado, así que escribí un pequeño comando Stata llamado covid19 para descargar, combinar, guardar y graficar estos datos.

El comando crea una tabla que contiene la fecha, el número de casos confirmados, el número de muertes y el número de recuperados. Agregué una variable calculada llamada newcases, que es la diferencia entre casos confirmados durante dos días contiguos.
Los datos originales incluyen todos los países que informan, por lo que agregué una opción country() que me permite ver la tabla de un país en particular.




Agregué una opción graph() que grafica el número de casos confirmados.

Figura 1. Casos confirmados de COVID-19 en Estados Unidos



La opción saving() guarda loa datos en un archivo llamado covid19_usa.dta.



Me gusta mi comando covid19, pero no tengo planes de distribuirlo. No lo he probado a fondo, y podría volverse inútil si Johns Hopkins cambia sus datos. Así que le mostraré los pasos para descargar y procesar los datos para que pueda hacerlo usted mismo. Si los datos cambian, tendrá las herramientas para modificar su código y descargar datos futuros.Escribir X=J(3,4,5) en el símbolo de dos puntos, Mata compila y ejecuta este codigo. J(r,c,v) es la función de Mata que crea una matriz rxc, dobde cada uno de sus elemntos es v. La expresión en el lado derecho del operador = se asigna al simbolo del lado izquierdo.

Datos de GitHub de la Universidad Johns Hopkins
GitHub es un sitio web/plataforma popular para el desarrollo y distribución de software. El Centro de Ciencias e Ingeniería de Sistemas de la Escuela de Ingeniería Johns Hopkins Whiting tiene un repositorio GitHub que incluye datos COVID-19 actualizados regularmente de todo el mundo. Los datos en bruto están disponibles aquí: datos de Johns Hopkins GitHub.

Figura 2. Datos de GitHub de Johns Hopkins para COVID-19





Los datos se almacenan en archivos .csv separados para cada día. Hagamos clic en el archivo llamado 29-01-2020.csv para ver su contenido. Este archivo contiene datos para la Provincia/Estado, el País/Región, la fecha y hora de la Última Actualización, el número de casos confirmados, el número de muertes y el número de recuperados.

Figura 3: Contenido de 01-29-2020.csv


Puede ver los datos sin procesar, delimitados por comas haciendo clic en el botón "Sin procesar" junto a la flecha roja. Tenga en cuenta que agregué la flecha roja; no aparece en el sitio web.


Figura 4: Datos sin procesar delimitados por comas en 01-29-2020.csv




Puede importar estos datos sin procesar desde el sitio web a Stata utilizando import delimited
El nombre del archivo es la URL en la barra de direcciones de su navegador web.

Es probable que su navegador web ajuste la URL a una segunda línea. Tenga en cuenta que este es un comando de una línea en Stata. Luego puedo describir (describe) y enumerar (list) los datos en Stata.


¡Lo hicimos! ¡Importamos con éxito los datos en bruto para el 29 de enero de 2020, desde el repositorio Johns Hopkins de GitHub a Stata! Es solo un archivo y hay al menos un problema obvio con los datos (la variable denominada ïprovincestate), pero es un buen lugar para comenzar.

Usando confirm e if para arreglar nombres de variables

Aprendí a través de prueba y error que la variable provincestate se importa como ïprovincestate en algunos archivos y provincestate en otros. Queremos importar muchos archivos, y no queremos tener que revisar cada archivo manualmente. Así que usemos confirm para verificar en cada archivo una variable llamada ïprovincestate.




Si la variable ïprovincestate existe, el comando guardará un valor de cero en _rc. Podemos usar este resultado en una sentencia if que renombre (rename) y etiquete (label) correctamente la variable.




Esta base de datos contiene la variable ïprovincestate, así que los comandos dentro del bloque if son ejecutados. Podemos checar esto usando describe.




Nuestra base de datos ahora contiene una variable llamada provincestate. Escribamos confirm variable otra vez para ver qué sucede si la variable ïprovincestate no está en nuestra base.


Esta base de datos no contiene ninguna variable llamada ïprovincestate, por lo que confirm variable produce un mensaje de error. Si ejecutamos confirm variable dentro de un archivo do, el archivo do se detendrá. Podemos usar capture para permitir que nuestro do continúe ejecutándose incluso si confirm variable produce un error.



Tenga en cuenta que _rc es igual a 111, que no es igual a 0. Por lo tanto, el siguiente código importará los datos sin procesar y "arreglará" ïprovincestate si es necesario.



Usar macros para importar archivos distintos

A continuación, veamos cómo las macros pueden ayudarnos a importar diferentes archivos del sitio web. Podemos almacenar palabras o números temporalmente en la memoria usando macros. Las macros pueden ser locales o globales. Las macros globales, una vez definidas, están disponibles en cualquier lugar de Stata. Las macros locales existen únicamente dentro del programa o do-file en el que están definidas. Puede definir una macro local como esta:





Puede hacer referencia a la macro escribiendo una comilla simple a la izquierda del nombre de la macro y una apostrofe simple a la derecha del nombre de la macro.



Podemos crear macros al combinar otras macros, como esta:



Deseamos importar archivos con nombres como 29-01-2020.csv. Tenga en cuenta que el mes incluye un "cero a la izquierda". Los meses 1–9 se especifican como “01”, “02”, etc. Los meses 10–12 se especifican como “10”, “11” y “12”. Necesitamos una forma de asignar valores a las macros locales que incluya un cero inicial cuando sea apropiado. La función string() es una forma de hacer esto.



La función string() para la macro month almacenó el número 3 en una cadena de dos caracteres con un cero a la izquierda. La función string() para la macro day almacenó el número 19 en una cadena de dos caracteres con un cero inicial, pero el cero inicial no es necesario. Esto nos permitirá especificar fechas arbitrarias con el formato correcto para los archivos que deseamos importar.

A continuación, consideremos el nombre de archivo completo. La mayor parte del nombre de archivo largo es el mismo para cada archivo. Almacenemos la URL de los nombres de archivo en una macro local.




Esto nos permite especificar un nombre de archivo como este:


Usar bucles para importar múltiples archivos
Podemos repetir un comando o una colección de comandos colocándolos en un bucle. Una forma de hacerlo es con forvalues.


forvalues month = 1/12 {
   display "month = `month'"

Note que month está guardada como una macro local, y podemos referirla como `month' dentro del bucle. Así, los resultados de nuestro bucle lucen así:


También podemos crear un bucle dentro de un bucle. Por ejemplo, podemos crear un bucle de días dentro de los meses, como esto:

Los resultados de este ciclo son bastante largos, por lo que he omitido la mayor parte de la salida.



Usemos nuestro bucle para crear nombres para los archivos que deseamos descargar.



Este ciclo también devuelve una gran cantidad de salida, por lo que he omitido la mayor parte por brevedad. Tenga en cuenta que la función string() agrega ceros iniciales para mes y día cuando sea necesario.





Podemos usar la macro URL junto con import delimited para importar los datos sin procesar de todos los días en 2020. Tendremos que borrar (clear) la memoria de Stata antes de importar cada archivo de datos sin procesar. Luego, podemos guardar (save) una copia de cada archivo como un conjunto de datos Stata.




Estoy seguro de que ya ha anticipado la falla con el código anterior. Se repite todos los días de cada mes de 2020. Pero los archivos de datos comienzan el 21 de enero de 2020, por lo que no hay archivos de datos para el 1 de enero. Nuestro programa devuelve un mensaje de error.




También se agregarán nuevos datos todos los días, y me gustaría importar datos futuros una vez que se publiquen. Hay muchas formas inteligentes de manejar esta situación. Una forma es simplemente preceder import delimited y save con la capture. Los archivos de datos se importarán si existen. Si el archivo de datos no existe, el programa continuará. Es un método lento y crudo, pero funcionará para nuestros propósitos.



Nuestro truco con capture funcionó, y puedo ver una lista de archivos de datos Stata en mi directorio local.



Vamos a abrir el archivo 01-22-2020.dta y a describir los datos.




Este es uno de esos archivos que contienen la variable ïprovincestate. Aprendimos cómo solucionar esto antes usando confirm e if, así que vamos a poner nuestro "arreglo" en nuestro código y volver a ejecutarlo. Tenga en cuenta que he agregado la opción ,replace a los comandos de guardar porque los archivos ya existen en nuestro directorio.



Ahora podemos describir la base de datos 01-22-2020.dta y verificar que la variable ïprovincestate ha sido cambiada a provincestate.




Nuestro directorio local ahora contiene una colección de bases de datos Stata que queremos combinar en un solo archivo. Podemos hacer esto usando append. Podemos agregar dos bases de datos manualmente de esta forma:




Pero eso sería tedioso y tendríamos que actualizar continuamente nuestro código. Otro ciclo nos permitiría automatizar este proceso. Tenga en cuenta que he usado el truco de capture antes de append porque no tenemos un archivo para todos los días de 2020.



Describí nuestros datos y noté que hay dos nuevas variables. Algunos de los archivos de datos sin procesar contienen las variables latitude y longitude, y se han agregado a nuestro conjunto de datos completo.


Un listado de las últimas 10 observaciones confirma que la base de datos incluye algunos datos para latitud y longitud.


Conclusión y objetivos para la próxima vez

Detengámonos aquí y pensemos en lo que hemos logrado. Hemos descargado con éxito todos los datos en bruto disponibles para COVID-19 del repositorio GitHub de Johns Hopkins y los hemos combinado en un único conjunto de datos utilizando el siguiente código:





Muchos de ustedes notarán que podríamos realizar esta tarea con un solo bucle (pista: ¡use frames!). Pero quería mantener las cosas lo más simples que sea posible en esta publicación. Guardemos este conjunto de datos para poder usarlo más tarde.





Hay muchas cosas que podríamos hacer con este conjunto de datos en bruto. Podríamos crear datos de series temporales para examinar patrones a lo largo del tiempo. Podríamos hacer esto por país o incluso provincias o estados dentro de los países. Y tenemos información sobre la latitud y la longitud de algunos de los datos, por lo que podríamos explorar patrones por hora y ubicación. Discutiré esto en futuras publicaciones.

Tenga en cuenta que no hemos verificado ni limpiado estos datos. El código anterior y los datos resultantes deben usarse solo con fines educativos.

Eso es todo por hoy. ¡Gracias por leernos!














miércoles, 25 de marzo de 2020

Programando un comando de estimación en Stata: Mata101.


David M. Drukker, Director Ejecutivo de Econometría.

Introduzco a Mata, el lenguaje de programación matricial que es parte de Stata.
Esta es la décimo primera publicación de la serie Programando un comando de estimación en Stata. Te recomiendo que empieces por el principio.

Conociendo Mata
Mata es un lenguaje de programación matricial que es parte de Stata. El código mata es rápido porque está compilado en código objeto que se ejecuta en una maquina virtual; escriba help m1_how para más detalles.

El camino más sencillo para aprender Mata es usarlo. Comienzo con una sesión interactiva. (Puedes encontrar útil escribirlo también.)

Ejemplo 1: una primera sesión interactiva de Mata




Escribir mata: hace que Stata abra una sesión de Mata. Escribir end termina la sesión de Mata, volviendo así a Stata. El símbolo de punto . indica que Stata está pidiendo algo que hacer. Después de que escribes mata:, el símbolo de dos puntos: es el compilador de Mata que pide algo por hacer.

Escribir X=J(3,4,5) en el símbolo de dos puntos, Mata compila y ejecuta este codigo. J(r,c,v) es la función de Mata que crea una matriz rxc, donde cada uno de sus elemntos es v. La expresión en el lado derecho del operador = se asigna al simbolo del lado izquierdo.

Escribir X por sí mismo provoca que Mata despliegue lo que contiene X, que es una matriz 3x4 de cincos. Las expresiones no asignadas muestran sus resultados. Escriba help m2_exp para obtener detalles sobre las expresiones.

Escribir  w=(1::4) hace que Mata use el operador de rango de columna para crear un vector columna de 4x1 que se asigna a w y que se despliega cuando se escribe w solamente. Escriba help m2_op_range para detalles y una discusión sobe el operadr de rango de filas.

Al escribir v=X*w, Mata asigna el producto matricial de X veces w a v, que posteriormente despliego. Luego, ilustro que ‘ es el operador de transposición. Escriba help m2_exp, marker (remarks7) para obtener una lista de operadores.

Una vez más, escribir end finaliza la sesión de Mata.

En casi todo el trabajo que hago, extraigo submatrices de una matriz.

Ejemplo 2: extrayendo submatrices de una matriz


Utilizo r(seed) para configurar la semilla para el generador de números aleatorios, para después utilizar runiform(r,c) para crear una matriz 4x4 con desviaciones uniformes, la cual, subsecuentemente despliego.

Paso siguiente, utilizo el operador para unir filas, para crear el vector fila v y utilizar el operador para unir columnas \ para crear el vector columna u.        

Escriba help m2_op_join para más detalles.

Al escribir W[u,v] se extrae de W las filas especificadas en el vector u y las columnas especificadas en el vector v.

Con frecuencia extraigo bloques rectangulares definidos por un elemento superior izquierdo y un elemento inferior derecho. Ilustro esta sintaxis escribiendo
W[| 1,1 \ 3,3 |]

En detalle, [| abre una extracción de subíndice de rango, 1,1 es la dirección del elemento superior izquierdo, \ separa el elemento superior izquierdo del elemento inferior derecho, 3,3 es la dirección del elemento inferior derecho y |] cierra una extracción de subíndice de rango. 
Escriba help m2_subscripts para obtener detalles.

Irónicamente, cuando estoy haciendo programación matricial, con frecuencia quiero el operador elemento por elemento en lugar del operador matriz. Prefije a cualquier operador de matriz en Mata con dos puntos (:) para obtener el equivalente elemento por elemento.

Ejemplo 3: operadores de elementos






Extraigo las cuatro filas inferiores de W, almaceno esta matriz en W y visualizo este nuevo W. Luego, creo un vector conformable en fila v, realizo una multiplicación de v por elementos a través de las columnas de W y visualizo el resultado. No puedo escribir v*W porque v 3×1 no es conformable con W 3×3. Pero puedo, y lo hago, escribir v’*W porque v’ es de orden 1×3 y es conforme con W 3×3.

El ejemplo 4 usa un operador lógico por elementos.

Ejemplo 4: operador lógico por elementos



Muestro el resultado de comparar el elemento conformable v con W. Escriba help m2_op_colon para más detalles.

Datos de Stata en Mata

La función Mata st_data() crea una matriz Mata que contiene una copia de los datos del conjunto de datos Stata en la memoria. La función Mata st_view() crea una vista Mata de los datos en el conjunto de datos Stata en la memoria. Las vistas actúan como matrices, pero hay una compensación de espacio-velocidad. Las copias son rápidas a costa de usar el doble de memoria. Las vistas son más lentas, pero usan poca memoria extra.

Copiar los datos de Stata en Mata duplica la memoria utilizada, pero los valores se almacenan en la memoria de Mata. Cada vez que una función Mata solicita un valor de una matriz, lo encuentra de inmediato. Por el contrario, una vista de los datos en Stata apenas aumenta la memoria utilizada, pero los valores están en la memoria de Stata. Cada vez que una función Mata solicita un valor de una vista, encuentra un letrero que le dice dónde se puede obtener ese valor en Stata.

Ejemplo 5: Datos de Stata en Mata

Después de enumerar las primeras tres observaciones sobre seis variables en el conjunto de datos auto, abro Mata, uso st_data() para poner una copia de todas las observaciones en mpg, headroom y trunk en la matriz Mata Y, y uso st_view() para crear la vista Mata X con todas las observaciones en rep78, turn y foreign.

Después de unir las filas Y y X para crear V, muestro las primeras 3 filas de V. Observe que falta la tercera observación en rep78 y que las matrices y vistas de Mata pueden contener valores faltantes.

Cambiar el valor de un elemento en una vista cambia los datos en Stata. Ilustraré este punto reemplazando el elemento (3,1) de la vista X con 7, mostrando las primeras tres filas de la vista y enumerando las primeras tres observaciones en rep78, turn y foreign.

Copiando matrices entre Mata y Stata

La función Mata st_matrix() coloca una copia de una matriz Stata en una matriz Mata, o coloca una copia de una matriz Mata en una matriz Stata. En el ejemplo 6, V = st_matrix("B") coloca una copia de la matriz Stata B en la matriz Mata V.

Ejemplo 6: creando una copia de una matriz Stata en un vector Mata


En el ejemplo 7, st_matrix(“Z”,W) coloca una copia de la matriz Mata W en la matriz Stata Z.

Ejemplo 7: creando una copia de una matriz Mata en un vector Stata


Cadenas de texto

Las matrices Mata pueden ser matrices de cadenas de texto.

En mi trabajo, con frecuencia tengo una lista de variables en un escalar de cadena de texto con la que es más fácil trabajar como un vector de cadena de texto.

Ejemplo 8: convirtiendo una lista de texto a un vector de texto


Utilizo tokens() para crear el vector de texto s2 de la lista de texto s1.

Flujo de control

Mata tiene construcciones para recorrer un bloque de código encerrado entre llaves o solo ejecutarlo si una expresión es verdadera.

Con frecuencia uso la construcción for() para recorrer un bloque de código.


En este ejemplo, configuro i en el valor inicial de 1. El bucle continuará siempre que i sea menor o igual que 3. Cada vez que se ejecuta el bucle, se ejecuta el bloque de código encerrado entre las llaves y 1 se agrega al valor actual de i. El bloque de código muestra el valor de i. El ejemplo 9 ilustra estos puntos.

Ejemplo 9: un bucle for


A veces, quiero ejecutar un bloque de código siempre que una condición sea verdadera, en cuyo caso uso un ciclo while, como en el bloque de código 2 y el ejemplo 10.

Code block 2: while()



Establezco i en 7 y repito el bloque de código entre las llaves mientras que i es mayor que 5. El bloque de código muestra el valor actual de i, luego resta 1 de i.

Ejemplo 10: un bucle while


La construcción if solo ejecuta un bloque de código si una expresión es verdadera. Usualmente uso la construcción if-else que ejecuta un bloque de código si una expresión es verdadera y otro bloque de código si la expresión es falsa.

Ejemplo 11: una construcción if-else


Llamando Mata en una línea

Con frecuencia hago llamadas de una línea a Mata desde Stata. Una llamada de una línea a Mata hace que Stata abra Mata, compile y ejecute la línea de código de Mata, y vuelva a aparecer en Stata.

Ejemplo 12: una línea llama a Mata

En el ejemplo 12, utilizo una línea para llamar a Mata mata: st_matrix(“Q”,I(3)) para colocar una copia de la matriz Mata que retorna la expresión Mata I(3) dentro de la matriz Stata Q. Después de la linea que llama a Mata, estoy de regreso en Stata, así que uso matrix list Q para mostrar que la matriz Stata Q es una copia de la matriz Mata W.

Hecho y sin hacer

Usé una sesión interactiva para presentar a Mata, el lenguaje de programación matricial que forma parte de Stata.

En la siguiente publicación, muestro cómo definir las funciones de Mata.


miércoles, 19 de febrero de 2020

Programando un comando de estimación en Stata: Usando una subrutina para analizar una opción compleja.


David M. Drukker, Director Ejecutivo de Econometría.

Realizo dos mejoras en el comando que implementa el estimador de mínimos cuadrados ordinarios (OLS) que discutí en Programando un comando de estimación en Stata: Permitiendo opciones. 

Primero, agrego una opción para un estimador robusto por conglomerados de la varianza-covarianza del estimador (VCE). En segundo lugar, hago que el comando acepte la sintaxis moderna para un estimador robusto o un clúster robusto del VCE. En el proceso, uso subrutinas en mi programa ado para facilitar el análisis y analizo algunos trucos de análisis avanzados. 

Esta es la décima publicación de la serie Programando un comando de estimación en Stata: Permitir restricciones de muestra y variables factor. Te recomiendo que empieces por el principio. 

Permitiendo un estimador robusto o robusto por conglomerados (VCE)
La sintaxis de myregress9, la cual discuto en Programando un comando de estimación en Stata: Permitiendo opciones, es 

myregress9 depvar [indepvars] [if] [in] [, robust noconstant

La sintaxis de myregress10, el cual analizo aquí, es 

myregress10 depvar [indepvars] [if] [in] [, vce(robust | cluster clustervar) noconstant

Por defecto, myregress10 estima el VCE asumiendo que los errores son independientes e idénticamente distribuidos (IID). Si la opción vce(robust) se especifica, myregress10 usa el estimador robusto de el VCE. Si la opción vce(cluster clustervar) se especifica, myregress10 usa el estimador robusto por conglomerados del VCE. Vea Cameron y Trivedi (2005), Stock y Watson (2010), Wooldridge (2015) para una introducción a OLS; vea Programando un comando de estimación en Stata: Usado comandos matriciales y funciones para calcular objetos MCO para las formulas y las implementaciones matriciales en Stata. 

Recomiendo que dé un clic en el nombre del archivo para descargar el código para mi myregress10.ado. Para evadir el desplazamiento, vea el código en el editor de archivos do, o en su editor de texto favorito para ver los números de línea. 

Code block 1: myregress10.ado





El comando syntax en la línea 5 pone cualquier cosa que el usuario especifique en vce() dentro de una macro local llamada vce. Por ejemplo, si el usuario escribe:




La macro local vce contendrá “hello there”. Si el usuario no especifica algo en la opción vce(), la macro local vce estará vacía. La línea 14 usa está condición para ejecutar las líneas 15-21 solo si el usuario ha especificado algo en la opción vce.

Cuando el usuario especifica algo en la opción vce, la línea 15 llama a la subrutina ado my_vce_parse para analizar qué hay en la macro local vce. my_vce_parse guarda el nombre de la variable clúster en r(clustervar) y aborda condiciones de error, tal como analizo a continuación. La línea 16 guarda “robust” dentro de la macro local vcetype, y la línea 17 guarda el contenido de la macro local r(clustervar) creada por my_vce_parse dentro de la macro local clustervar. 

Si el usuario no especifica algo en vce(), la macro local vcetype estará vacía y la línea 36 asegura que myregress10 calcule un estimador IID del VCE.

Las líneas 19 y 20 se ejecutan solamente si la macro local clustervar no está vacía. La línea 19 la variable a utilizar, cuyo nombre está guardado en la macro local touse, para abordar valores faltantes en la variable clúster, cuyo nombre está guardado en clustervar. La línea 20 ordena la base de datos en orden ascendente de la variable clúster. Los usuarios no quieren comandos de estimación reordenando sus datos. En la línea 2, especifico la opción sortpreserve en program define para mantener la base de datos en el orden en el que estaba cuando myregress fue ejecutado por el usuario.


Las líneas 36-65 calculan el estimador requerido para el VCE. Recuerde que la macro local vcetype está vacía o contiene “robust” y que la macro local clustervar está vacía o contiene el nombre de la variable clúster. Las condicionales if y else usan los valores guardados en vcetype y clustervar para ejecutar uno o tres bloques de código.


1. Las líneas 38-42 calculan un estimador robusto del VCE cuando vcetype contiene “robust” y clustervar está vacía.

2. Las líneas 45-53 calcula un estimador robusto por conglomerados del VCE cuando vcetype contiene “robust” y clustervar contiene el nombre de la variable clúster.

3. Las líneas 60-64 calculan un estimador IID del VCE cuando vcetype no contiene “robust”.


La línea 73 guarda el nombre de la variable clúster en e(clustervar), si la macro local clustervar no está vacía. 

Las líneas 78-111 define la rclass subrutina ado my_vce_parse, la cual realiza dos tareas. Primero, guarda el nombre de la variable clúster en la macro local r(cluster) cuando el usuario especifica vce(cluster clustervar). Segundo, encuentra casos en los cuales el usuario especifique un error de sintaxis en vce() y reporta un error en tales casos. 

Poniendo estos detalles de análisis dentro de una subrutina hace al comando principal más fácil de seguir. Recomiendo que encapsulen detalles en las subrutinas. 

La subrutina ado my_vce_parse es local al comando ado myregress10; el nombre my_vce_parse está en un espacio para nombres local en myregress10, y my_vce_parse puede ser ejecutado solamente desde myregress10

La línea 79 usa syntax para guardar lo que sea que el usuario especifique en la opción vce() de la macro local vce, La línea 81 pone el número de letras en vce dentro de la macro local case. La línea 83 provoca que la subrutina ado my_vce_error despliegue un mensaje de error y reporte un código de error 498 cuando haya más de dos palabras en vce. (RTecuerde que vce debe contener robust, o bien, cluster clustervar.) 

Habiendo descartado los casos con más de dos palabras, la línea 87 guarda lo que la macro local vce contenga en la macro local 0. La línea 88 usa syntax para analizar lo que está en la macro local 0. Si el usuario especifica vce(robust), o una abreviación válida del mismo, syntax guarda “robust” en la macro local robust; de otra manera, la macro local robust estará vacía. Si el usuario especifica vce(cluster algo), o una abreviación válida de cluster, syntax guarda “cluster” en la macro local cluster; de otra manera, la macro local cluster estará vacía. La opción * hace que syntax ponga cualquier opción remanente dentro de la macro local options. En este caso, syntax guardará el algo en la macro local options. 

Recuerde el truco utilizado en las líneas 87 y 88. La opción de analizar es frecuentemente mucho más fácil al guardar lo que la macro local contiene en la macro local 0 y usando syntax para analizarlo. 

Cuando hay dos palabras en la macro local vce, las líneas 91-100 aseguran que la primera palabra sea “cluster” y que la segunda palabra, guardada en la macro local options, sea el nombre de una variable numérica. Cuando todo está bien, la línea 100 guarda el nombre de esta variable numérica en la macro local clustervar. Las líneas 95-98 usan una construcción delicada para desplegar un error personalizado. En lugar de dejar que confirm despliegue un mensaje de error, las líneas 95-98 usan capture y una condicional if para desplegar nuestro mensaje personalizado de error. En detalle, la línea 95 usa confirm para confirmar que la macro local options contenga el nombre de una variable numérica. capture pone el código producido por confirm en el escalar _rc. Cuando options contenga el nombre de una variable numérica, confirm produce el código de retorno 0 y capture guarda este código de retorno positivo en _rc. 

Cuando todo está bien, la línea 109 limpia lo que sea que esté en r(), y la línea 110 guarda el nombre de la variable clúster en r(clustervar). 

Las líneas 113-118 definen la subrutina ado my_vce_error, la cual despliega un mensaje personalizado de error. Semejante a my_vce_parse, ,my_vce_error es local en myregress10.ado. 

Hecho y sin hacer

Agregué una opción para el estimador robusto por conglomerados del VCE, e hice que myregress10 aceptara la sintaxis moderna tanto para un estimador robusto como uno robusto por conglomerados para el VCE. En el proceso, utilice subrutinas en myregress10.ado para facilitar el análisis de sintaxis, y utilice algunos trucos avanzados sobre esto. 

Leer myregress10.ado hubiera sido más difícil de leer si no hubiera usado subrutinas para simplificar la rutina principal. 

Aunque parezca que he cubierto todos los matices posibles, solo he tratado algunos. Escriba help syntax para obtener más detalles sobre las opciones de análisis mediante el comando syntax. 

Referencias
Cameron, A. C., and P. K. Trivedi. 2005. Microeconometrics: Methods and applications. Cambridge: Cambridge University Press.

Stock, J. H., and M. W. Watson. 2010. Introduction to Econometrics. 3rd ed. Boston, MA: Addison Wesley New York.

Wooldridge, J. M. 2010. Econometric Analysis of Cross Section and Panel Data. 2nd ed. Cambridge, Massachusetts: MIT Press.

Wooldridge, J. M. 2015. Introductory Econometrics: A Modern Approach. 6th ed. Cincinnati, Ohio: South-Western.