4.3 Iteración

En análisis de datos es común implementar rutinas iteraivas, esto es, cuando debemos aplicar los mismos pasos a distintas entradas. Veremos que hay dos paradigmas de iteración:

  1. Programación imperativa: ciclos for y ciclos while.

  2. Programación funcional: los ciclos se implmentan mediante funciones,

La ventaja de la programación imperativa es que hacen la iteración de manera clara, sin embargo, veremos que una vez que nos familiarizamos con el paradigma de programación funcional, resulta en código más fácil de mantener y menos propenso a errores.

Ciclos for

Supongamos que tenemos una base de datos y queremos calcular la media de sus columnas numéricas.

Podemos crear el código para cada columna pero esto involucra copy-paste y no será muy práctico si aumenta el número de columnas:

Con un ciclo for sería:

Los ciclos for tienen 3 componentes:

  1. La salida: salida <- vector("double", 4). Es importante especificar el tamaño de la salida antes de iniciar el ciclo for, de lo contrario el código puede ser muy lento.

  2. La secuencia: determina sobre que será la iteración, la función seq_along puede resultar útil.

  1. El cuerpo: salida[[i]] <- mean(df[[i]]), el código que calcula lo que nos interesa sobre cada objeto en la iteración.

Calcula el valor máximo de cada columna numérica de los datos de ENLACE 3o de primaria enlacep_2013_3.

  • Recordando la limpieza de datos de la sección anterior en uno de los últimos ejercicios leíamos archivos de manera iteativa. En este ejercicio descargaremos un archivo zip con archivos csv que contienen información de monitoreo de contaminantes en ciudad de México (RAMA), en particular PM2.5. Y juntaremos la información en una sola tabla, la siguiente instrucción descarga los datos en una carpeta data.
  • Enlistamos los archivos xls en la carpeta.

Tu turno, implementa un ciclo for para leer los archivos y crear una única tabla de datos. Si pegas los data.frames de manera iterativa sugerimos usar la función bind_rows().

Programación funcional

Ahora veremos como abordar iteración usando programación funcional.

Regresando al ejemplo inicial de calcular la media de las columnas de una tabla de datos:

Podemos crear una función que calcula la media de las columnas de un data.frame:

Y podemos extender a crear más funciones que describan los datos:

Podemos hacer nuestro código más general y compacto escribiendo una función que reciba los datos sobre los que queremos iterar y la función que queremos aplicar:

Ahora utilizaremos esta idea de pasar funciones a funciones para eliminar los ciclos for.

La iteración a través de funciones es muy común en R, hay funciones para hacer esto en R base (lapply(), apply(), sapply()). Nosotros utilizaremos las funciones del paquete purrr,

La familia de funciones del paquete iteran siempre sobre un vector (vector atómico o lista), aplican una función a cada parte y regresan un nuevo vector de la misma longitud que el vector entrada. Cada función especifica en su nombre el tipo de salida:

  • map() devuelve una lista.
  • map_lgl() devuelve un vector lógico.
  • map_int() devuelve un vector entero.
  • map_dbl() devuelve un vector double.
  • map_chr() devuelve un vector caracter.
  • map_df() devuelve un data.frame.

En el ejemplo de las medias, map puede recibir un data.frame (lista de vectores) y aplicará las funciones a las columnas del mismo.

Usaremos map para ajustar un modelo lineal a subconjuntos de los datos mtcars determinados por el cilindraje del motor.

Podemos usar la notación . para hacer código más corto:

Usemos map_** para unir tablas de datos que están almacenadas en múltiples archivos csv.

En este caso es más apropiado usar map_df

Ejercicio

  • Usa la función map_** para calcular el número de valores únicos en las columnas de iris.

  • Usa la función map_** para extraer el coeficiete de la variable wt para cada modelo: