Proyecto final: “Integrando el pensamiento computacional en la enseñanza de las ciencias con R”

“Data, data, data, data, data, data, ¿cómo se bebe de una catarata?” (“Data, data” por Jorge Drexler, del álbum “Bailar en la cueva”, 2014)

Introducción

El objetivo de este proyecto es mostrar un ejemplo de integración del pensamiento computacional en el nivel secundario (últimos dos años) en las áreas de matemática y/o ciencias (tanto naturales como sociales). Trabajaremos con datos que tengan significancia en un contexto escolar utilizando un paquete estadístico muy conocido en la ciencia de datos: R. Utilizaremos R para la modelización en las áreas curriculares mencionadas trabajando con datos reales y abiertos.
El tema a trabajar es la contaminación del aire en la Ciudad Autónoma de Buenos Aires.


Presentación de los datos

Utilizaremos un conjunto de datasets sobre calidad del aire, los cuales pertenecen al repositorio de Buenos Aires Data. Son 3(tres) datasets correspondientes a las mediciones registradas en los 3 últimos años (2017, 2018, 2019). Los datos a trabajar contienen registros diarios de esos tres años sobre tres contaminantes: CO (monóxido de carbono); PM10 (material particulado de diámetro menor a 10 micrones) y NO2, medidos en tres estaciones ubicadas en distintos puntos de la ciudad (Centenario; La Boca y Córdoba). Nuestra intención es mostrar los diferentes niveles de contaminación para cada una de las estaciones y cada uno de los años en un mapa de la ciudad, mostrando los valores en forma de burbuja, de modo que el diámetro de la burbuja sea proporcional al valor del contaminante. Para esto vamos a necesitar dos datasets más: uno con las coordenadas de los barrios de la ciudad y otro con la ubicación de las estaciones de medición. Ambos datasets los tomaremos del sitio Buenos Aires Data.

Exploración del problema

Las preguntas que nos interesa explorar en este ejercicio son: ¿Cómo es la calidad del aire en la ciudad de Buenos Aires? ¿Varía la misma de acuerdo a determinadas condiciones como la hora, el día, o el mes? En los últimos 3 años, ¿mejoró, empeoró, o se mantuvo igual la calidad del aire? ¿Hay algún patrón en las zonas de medición? ¿cuáles podrían ser las razones de los patrones encontrados?

Para poder contestar estas preguntas utilizaremos los siguientes instrumentos:

PASO 1: Limpieza de datos

Luego de bajar nuestro conjunto de datos, lo analizamos y vemos que hay datos faltantes, hay datos incosistentes, etc. Para poder trabajarlos entonces, necesitamos limpiar esos datos y modificarlos para que tengan el formato más cómodo para poder operar sobre ellos y responder nuestras preguntas.
Lo primero que debemos hacer es cargar las librerías que contienen las funciones que utilizaremos para limpiar nuestros datos. En nuestro caso utilizaremos dos librerías: tidyverse que es una librería clásica de R, y lubridate que nos ayuda a trabajar con fechas. Cargamos entonces dichas librerías:

library(tidyverse)
library(lubridate)

El siguiente paso es cargar los datos sobre calidad del aire del año 2017 y guardarlos en una variable que llamaremos “q_aire2017”.
Al inspeccionar los datos (no viene ahora al caso explicar cómo), nos encontramos con que hay mediciones que en vez de tener un valor numérico, tienen un texto para significar que no se registró el dato (nosotros no sabemos por qué, ni tampoco interesa en este momento saberlo). El texto que utilizaron quienes trataron los datos antes de ponerlos a disposición en el repositorio fue “s/d” y “S/D”.
También encontramos que uno de los valores ingresados no es un número sino una expresión: “<0,5”. Desconocemos por qué figura esa expresión (y repito, no nos interesa saberlo, por ahora) pero sabemos que si queremos operar numéricamente con ese dato (por ejemplo calcular un promedio de una serie de valores donde uno es “<0,5”), entonces debemos reemplazarlo por un valor que sí nos permita operar con él y no nos moleste en nuestro cálculo.
En R, ese valor es “NA”, que significa que ese valor no está disponible y R lo ignorará, no lo tomará en cuenta a la hora de realizar un cálculo.
A continuación vemos la función que nos permite leer los datos para calidad del aire de 2017 y reemplazar los valores no numéricos por el valor “NA”:

q_aire2017 <- read.csv2("/cloud/project/calidad-de-aire-2017.csv", 
                        na.strings = c("s/d", "S/D", "<0,05"))

Ahora que ya leímos los datos y los guardamos en nuestra variable, vamos a mostrar las 6 primeras y las 6 últimas filas de nuestro conjunto de datos a ver qué pinta tiene. Para eso utilizamos las funciones head() y tail:

head(q_aire2017)
##        FECHA HORA CO_CENTENARIO NO2_CENTENARIO PM10_CENTENARIO CO_CORDOBA
## 1 01/01/2017    1          0.70             NA              NA       0.81
## 2 01/01/2017    2          0.72             NA              NA       0.79
## 3 01/01/2017    3          0.72             NA              NA       0.82
## 4 01/01/2017    4          0.73             NA              NA       0.81
## 5 01/01/2017    5          0.73             NA              NA       0.73
## 6 01/01/2017    6          0.69             NA              NA       0.65
##   NO2_CORDOBA PM10_CORDOBA CO_LA_BOCA NO2_LA_BOCA PM10_LA_BOCA
## 1          19           19         NA           2           43
## 2          16           20         NA           2           46
## 3          23           19         NA           1           46
## 4          16           20         NA           2           51
## 5          11           20         NA           2           50
## 6          11           20         NA           2           49
tail(q_aire2017)
##           FECHA HORA CO_CENTENARIO NO2_CENTENARIO PM10_CENTENARIO
## 8647 31/12/2017   19            NA             NA              NA
## 8648 31/12/2017   20            NA             NA              NA
## 8649 31/12/2017   21            NA             NA              NA
## 8650 31/12/2017   22            NA             NA              NA
## 8651 31/12/2017   23            NA             NA              NA
## 8652 31/12/2017   24            NA             NA              NA
##      CO_CORDOBA NO2_CORDOBA PM10_CORDOBA CO_LA_BOCA NO2_LA_BOCA
## 8647       0.49          11           32       0.34          14
## 8648       0.48          12           32       0.33          14
## 8649       0.46          12           28       0.33          19
## 8650       0.46          18           26       0.34          23
## 8651       0.45          15           25       0.36          20
## 8652       0.45          13           24       0.37          22
##      PM10_LA_BOCA
## 8647           32
## 8648           31
## 8649           26
## 8650           24
## 8651           22
## 8652           22

Al examinar la “cabeza” y la “cola” de nuestro conjunto de datos, observamos que la columna "NO2_CENTENARIO (estos serían los valores del contaminante dióxido de nitrógeno de la estación Centenario) tiene valores no disponibles tanto al principio como al final, pero no sabemos qué ocurre en el medio.
Si quisiéramos echar un vistazo rápido a todos los valores de esa columna, podríamos usar la función table():

table(q_aire2017$NO2_CENTENARIO)
## 
##   0   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18 
##   1   6  28  71 118 179 218 232 244 285 308 352 380 371 363 407 406 349 
##  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36 
## 347 338 293 271 256 253 216 172 155 149 108 103  76  60  54  54  33  31 
##  37  38  39  40  41  42  43  44  45  46  47  48  49  52  53  56  59 
##  23  27  17  11   6   8   1   4   4   2   2   2   3   1   2   1   1

Y ahí podemos ver que hay varios valores, aunque algunos no estén disponibles, lo cual nos deja tranquilos. Si al aplicar la función table() a nuestro conjunto de datos de la columna NO2_CENTENARIO, no nos hubiera mostrado nada, eso significaría que para esa columna no hay ningún dato disponible.

Volviendo a nuestros datos, vemos que la primer columna, FECHA, es de tipo factor, lo cual no nos conviene a la hora de agrupar nuestros datos por mes por ejemplo. Si quisiéramos calcular el promedio por mes de los valores de NO2 de la estación Centenario, nos convendría que el atributo FECHA tuviera formato de fecha para poder operar con el mes y/o el día. Mejor sería, incluso, poder transformar esa columna FECHA en tres columnas MES, DIA, ANIO, cada una con su formato correspondiente.

Vamos a proceder entonces con esa operación convirtiendo primero el campo FECHA a tipo de dato “date”. Para esa operación vamos a utilizar la función mutate() que nos permite agregar columnas a nuestra tabla de datos y echaremos mano a las funciones que nos provee la librería lubridate para manejar fechas. En nuestro caso queremos agregar las columnas MES, DIA, ANIO y además queremos que esas columnas contengan los valores que están en la columna FECHA. Luego de esa operación vamos a mirar las seis primeras filas de nuestra tabla de datos para verificar que está todo como queríamos:

q_aire2017 <- q_aire2017 %>% mutate(FECHA = dmy(FECHA),
         DIA = day(FECHA),
         MES = month(FECHA),
         ANIO = year(FECHA))
head(q_aire2017)
##        FECHA HORA CO_CENTENARIO NO2_CENTENARIO PM10_CENTENARIO CO_CORDOBA
## 1 2017-01-01    1          0.70             NA              NA       0.81
## 2 2017-01-01    2          0.72             NA              NA       0.79
## 3 2017-01-01    3          0.72             NA              NA       0.82
## 4 2017-01-01    4          0.73             NA              NA       0.81
## 5 2017-01-01    5          0.73             NA              NA       0.73
## 6 2017-01-01    6          0.69             NA              NA       0.65
##   NO2_CORDOBA PM10_CORDOBA CO_LA_BOCA NO2_LA_BOCA PM10_LA_BOCA DIA MES
## 1          19           19         NA           2           43   1   1
## 2          16           20         NA           2           46   1   1
## 3          23           19         NA           1           46   1   1
## 4          16           20         NA           2           51   1   1
## 5          11           20         NA           2           50   1   1
## 6          11           20         NA           2           49   1   1
##   ANIO
## 1 2017
## 2 2017
## 3 2017
## 4 2017
## 5 2017
## 6 2017

Ahora vamos a eliminar la columna FECHA y a reordenar nuestra tabla poniendo al principio las tres columnas nuevas que creamos. Para eso utilizamos la función select() que selecciona las columnas que queremos tener:

q_aire2017 <- select(q_aire2017, DIA, MES, ANIO, HORA, CO_CENTENARIO, NO2_CENTENARIO, PM10_CENTENARIO, CO_CORDOBA, NO2_CORDOBA, PM10_CORDOBA, CO_LA_BOCA, NO2_LA_BOCA, PM10_LA_BOCA)
head(q_aire2017)
##   DIA MES ANIO HORA CO_CENTENARIO NO2_CENTENARIO PM10_CENTENARIO
## 1   1   1 2017    1          0.70             NA              NA
## 2   1   1 2017    2          0.72             NA              NA
## 3   1   1 2017    3          0.72             NA              NA
## 4   1   1 2017    4          0.73             NA              NA
## 5   1   1 2017    5          0.73             NA              NA
## 6   1   1 2017    6          0.69             NA              NA
##   CO_CORDOBA NO2_CORDOBA PM10_CORDOBA CO_LA_BOCA NO2_LA_BOCA PM10_LA_BOCA
## 1       0.81          19           19         NA           2           43
## 2       0.79          16           20         NA           2           46
## 3       0.82          23           19         NA           1           46
## 4       0.81          16           20         NA           2           51
## 5       0.73          11           20         NA           2           50
## 6       0.65          11           20         NA           2           49

Luego de pedir un listado de las seis primeras filas podemos ver que la tabla de datos ahora sí está lista para operar con ella, tal como queríamos. Vamos a aprovechar que ya tenemos nuestra tabla limpia para grabarla en un nuevo archivo el cual renombraremos sutilmente (calidad del aire, en vez de calidad de aire):

write.csv(q_aire2017, "./calidad-del-aire/calidad-del-aire-2017.csv")

Ahora vamos a agrupar nuestros datos para poder ver mes a mes el promedio de dióxido de nitrógeno (NO2):

q_aire2017 %>%
group_by(MES) %>%
    summarise(promedio_mensual_NO2 = mean(NO2_CORDOBA, na.rm = TRUE))
## # A tibble: 12 x 2
##      MES promedio_mensual_NO2
##    <dbl>                <dbl>
##  1     1                 14.8
##  2     2                 21.2
##  3     3                 17.5
##  4     4                 20.1
##  5     5                 23.2
##  6     6                 24.7
##  7     7                 23.6
##  8     8                 23.4
##  9     9                 24.4
## 10    10                 25.3
## 11    11                 20.7
## 12    12                 21.3

Ahora vamos a calcular para la estación Centenario que tiene valores no disponibles:

q_aire2017 %>%
group_by(MES) %>%
    summarise(promedio_diario_NO2 = mean(NO2_CENTENARIO, na.rm = TRUE))
## # A tibble: 12 x 2
##      MES promedio_diario_NO2
##    <dbl>               <dbl>
##  1     1                14.4
##  2     2                18.8
##  3     3                16.2
##  4     4                17.8
##  5     5                18.8
##  6     6                20.1
##  7     7                18.3
##  8     8                19.2
##  9     9                16.8
## 10    10                16.0
## 11    11                15.6
## 12    12                15.7

“NA” significa que no está disponible el dato, NaN, si existiera, sería numérica.

De este modo hemos terminado con nuestra limpieza de datos. Lo que sigue ahora es el análisis. Clic en el botón de abajo para continuar al siguiente paso.

Análisis