6 Manejo de grandes bases de datos en Stata

6.0.1 Estilo de codificación: mejorar velocidad y eficiencia

Esta introducción esta basada en Suggestions on Stata programming style de Nicholas J. Cox.

Un buen estilo de codificación es por sobre todo claridad. Lo más importante es tener una estrategia y seguirla. En esta sección nos enfocaremos en algunos consejos de codificación que nos van a permitir mejorar la velocidad y eficiencia en el uso de Stata. Este punto es especialmente relevante cuando se trabaja con grandes bases de datos. Una lista de formas básicas de aumentar la velocidad y eficiencia al manejar grandes bases de datos:

  • Testear siempre las condiciones claves. Hacerlo lo antes posible.
  • Utilizar summarize, meanonly cuando solo necesite este valor. Como regla general siempre he de preguntarme si lo que estoy obteniendo es útil o no.
  • Preferir foreach y forvalues sobre while. Son más rápidos.
  • Evitar el uso de macro shift. Con muchas variables, se vuelve muy lento. Mejor ocuapar un forvalues.
  • Evitar siempre que sea posible iterar sobre observaciones. Mata puede ser útil en este aspecto.
  • Evite usar preserve si es posible. Es atractivo para el programar pero puede ser costoso en tiempo cuando se utilizan grandes bases de datos. Es bueno profundizar en el uso de marksample con el fin de hacer programas efectivos.
  • Las variables temporales se eliminarán automáticamente al final de un programa, pero también considere la posibilidad de eliminarlas cuando ya no sean necesarias para minimizar la sobrecarga de memoria y reducir las posibilidades de que su programa se detenga porque no hay espacio para añadir más variables.
  • Especifique el tipo de las variables temporales para minimizar la sobrecarga de memoria. Si se puede utilizar una variable de bytes, especifique: generate bytes 'myvar' en lugar de dejar que se utilice el tipo por defecto, que desperdiciaría espacio de almacenamiento.
  • Evite utilizar una variable para mantener una constante; una macro o un escalar suele ser todo lo que se necesita.

6.0.2 Cargar grandes bases de datos

Cuatro aspectos que considerar siempre que se desee cargar en Stata alguna base de datos de un tamaño considerable:

  1. ¿Necesita todas las variables del conjunto de datos? Si no es así, cargue sólo las variables que necesite:
use var1 var2 var3 var4 using data1, clear
  1. ¿Necesita todas las observaciones del conjunto de datos? Si no es así, importe sólo las observaciones que necesite:
use data1 if state <= 9, clear
  1. ¿Su conjunto de datos ocupa más espacio de almacenamiento del necesario?:
  • Intenta leer tu conjunto de datos poco a poco y optimizarlo.
  • Además de solo importar determinadas observaciones o variables, se optimiza el espacio de almacenamiento utilizado compress.
  • Es posible inspeccionar la base de datos sin cargarla.
describe using data.1.dta
  1. ¿Su conjunto de datos contiene muchas observaciones idénticas?: Debe transformar el conjunto de datos en un conjunto de datos ponderado por frecuencia.

6.0.3 Reducir el uso de memoria

Cuando usted trabaja con un conjunto de datos en Stata, Stata debe cargar todo el conjunto de datos en la memoria de la computadora (RAM). Afortunadamente, las computadoras portátiles de hoy tienen más memoria que la mayoría de los servidores de hace 20 años, y la mayoría de la gente nunca tiene que preocuparse por la cantidad de memoria que Stata está utilizando.

¿Me tengo que preocupar de la memoria?

  • Sólo tienes que preocuparte por la memoria si el tamaño de tu conjunto de datos se aproxima a la cantidad de memoria del ordenador que utilizas, y si es mayor, definitivamente tienes un problema.
  • Si usted trabaja con grandes conjuntos de datos, debe tener cuidado: tratar de usar más memoria de la que tiene terminará mal.
  • ¿Cuando es mucho?: un Laptop tipico tiene 16gb.

6.0.4 Reducir el tamaño de la base de datos

Elimina datos innecesarios. Utiliza tipos de variables pequeños: help datatypes. Siempre que crees una variable es una buena practica especificar el tipo de dato. Acortar cadenas o codificarlas: strings requieren un byte por caracteres.

Sin embargo, para las observaciones todas tienen el mismo tamaño. Si tengo una variable que contiene: “Si”, “No”, “No lo se”. La variable utilizara 8 bytes por observación tal como si solo tuviese “No lo se”. Si tu cambias “no lo se” por “ns”. Ahora solo se utilizaran 2 bytes por observacion. Si tu cambias a: “S”, “N”, “I” solo utilizara un byte por observación.

Codificar la variable de string como una variable númerica tambien reduce el espacio en memerio a un byte por observación. Se recomiendo agregar labels y trabajar los string de esta forma cuando sea posible.

6.0.5 Eliminar siempre resultados intermedios, incluso temporales

Elimina resultados intermedios. Si creas variables para almacenar resultados intermedios, elimínelas tan pronto como haya terminado con ellas.

Por ejemplo, el siguiente código crea una variable llamada incomePovertyRatio sólo para poder crear una variable indicadora lowIncome que identifica a los sujetos cuyos ingresos son inferiores al 150% del nivel de pobreza

gen incomePovertyRatio = income/povertyLevel
gen lowIncome = (incomePovertyRatio < 1.5)
drop incomePovertyRatio

Debes eliminar la variable que no utilizas. Hacer esto siempre.

6.0.6 Dividir en trozos cuando sea posible

Si un conjunto de datos es demasiado grande para cargarlo en la memoria, para algunas tareas puede dividirlo en un conjunto de conjuntos de datos más pequeños y trabajar con ellos de uno en uno. Puede haber una variable categórica en el conjunto de datos de tal manera que un conjunto de datos separado para cada categoría funcionaría bien, o puede dividirlo por número de observación.

Dividir el conjunto de datos en trozos más pequeños probablemente sólo tiene sentido si puedes reducir el tamaño de cada trozo para que al final puedas combinarlos todos en un único conjunto de datos que pueda cargarse en la memoria.

6.0.7 Sort

sort en Stata es razonablemente eficiente: un millón de valores aleatorios pueden ponerse en orden creciente en menos de 3 segundos con sort x. Sin embargo, el comando no tiene una opción inversa para ordenar de mayor a menor.

gsort hace una ordenación decreciente de forma ineficiente - ordena de forma creciente en x, y luego ordena de forma creciente en menos _n. Esencialmente está haciendo:

  sort x
  gen long sortvar = -_n
  sort sortvar
  drop sortvar

Es mejor negar por usted mismo antes de una ordenación creciente:

generate negx = -x
  sort negx

6.0.8 Selección de muestra

Separar la selección de variables de la inclusión. Para minimizar la cantidad de memoria utilizada, necesitamos separar la decisión de selección de la muestra de la decisión de inclusión de la variable.

6.0.9 Precaución con reshape

El comando reshape es inexplicablemente lento. 13 segundos por millón de observaciones en mi computadora. Es importante pensar en codificación y buscar más opciones para hacer reshape. Se puede escribir un archivo separado para cada año de datos, y luego concatenarlos en un largo conjunto de datos en unos 2 segundos.

6.0.10 Subexpresiones comunes

A menudo, varias sentencias generate o replace tendrán subexpresiones comunes.

generate y = a if c==d & e==f
generate x = b if c==d & e==f

Una mejor opcion es precalcularlo.

generate smpl = c==d & e==f
generate y = a if smpl
generate x = b if smpl

6.0.11 Recomendaciones Adicionales

6.0.11.1 Collapse

collapse no es muy rápido. El autor, sin duda, supuso que aunque se utilizara con grandes conjuntos de datos, no estaría dentro de una iteración. Pero a veces lo está, y puede convertirse en el paso limitante de la velocidad en un programa de larga duración. Se puede reemplazar fácilmente con código más rápido, pero el beneficio total no es tan grande como uno esperaría. Mejor ocupar gtools.

6.0.11.2 Egen

egen tambien puede ser adecuado para que funcione más rapido. Vamos a ver un ejemplo calculando el máximo de una variable.

6.0.11.3 Regresiones en sub-grupos

Exiten varias opciones para calcular regresiones según el tipo de datos que queramos incluir en nuestra muestra. Vamos a ver distintas opciones y ver su desempeño en bases de datos grandes.

6.0.11.4 Recode

recode puede ser modificado utilizando matrices. Otra opción es utilizar ggtools

6.0.12 Resumen

  • Utilizar compress.
  • Mantener solo las variables que se van a utilizar.
  • Mantener solo las observaciones que se van a utilizar.
  • Cargar solo las variables y observaciones necesarias.
  • keepusing y nogen siempre para merge.
  • ftools y gtools (más detalles sección final).
  • Utilizar parallel (más detalles sección final).