1. INTRODUCCIÓN 2. ESTRUCTURA DE LOS DATOS 3. PROCESAMIENTO 4. ¡A DESCARGAR LOS DATOS 5. CONOCIENDO SF 6. MANOS A LA OBRA 7. CONOCIENDO GGPLOT



1- INTRODUCCIÓN

Arrancamos con todo. En este cuarto encuentro les proponemos un acercamiento superficial a los datos espaciales. Decimos que es superficial porque vamos a poder abordar una muy pequeña dimensión sobre lo que hace a este campo de análisis. En los siguientes tres encuentros realizamos operaciones espaciales, visualizaciones e informes. Particularmente estos encuentros proponen realizar un análisis de una política pública. La idea es aprender a través de ir haciendo. Creemos que una parte fundamental para este tipo de cursos es la práctica. De esta manera, proponemos analizar la ampliación de dispositivos de vacunación que realizó el Gobierno de la Ciudad de Buenos (GCBA) para poder vacunar a la población de mayores de 65 años.

Como es de público conocimiento, en el contexto de la pandemia, se realizó una campaña de vacunación antigripal a la población de mayores de 65 años como una las formas de disminuir el riesgo frente al Covid 19. En la página del GCBA se publica “La vacunación es obligatoria y gratuita para las personas incluidas dentro de los grupos de riesgo: Personal de salud, Embarazadas, Puérperas hasta 10 días postparto , Niños de 6 a 24 meses, Adultos mayores a partir de los 65 años, Personas de 2 a 64 años incluidas dentro de los grupos de riesgo (deben acreditar la condición de riesgo, ya sea con receta con indicación médica o evidencia física)”. Los dichos del Jefe de Gobierno de la Ciudad Buenos Aires complementan lo anterior “la vacuna antigripal obviamente no nos protege contra el coronavirus, pero es muy importante aplicársela, porque en el caso de que no la tuvieran, la combinación de ambas enfermedades complica mucho el cuadro”.

En este marco, para mejorar la cobertura, el GCBA propuso una política pública de ampliación de los vacunatorios recurriendo a las escuelas, iglesias y centros de días. Estos dispositivos se sumaron a la tradicional oferta que se brinda desde los Centros de Salud de Acción Comunitaria (CeSAC). Aunque en la página del GCBA se aclara que “no hay que ir a los hospitales y a los centros de salud como se hace todos los años”, estos centros funcionaron como vacunatorios. Entonces, el objetivo que se propone en el siguiente ejercicio es analizar y problematizar la política pública de ampliación de dispositivos públicos para vacunar a la población de 65 años con la vacuna antigripal .

Para cumplir con los objetivos propuestos se utiliza información publicada en el portal de datos del GCBA: la cartografía de los radios censales (producidas por el INDEC), la georreferencia de los vacunatorios (CeSAC, escuelas, centros religiosos, centros comunitarios), que temporalmente ampliaron la capacidad de suministrar la vacuna del sector público y los polígonos de comunas. Para armar el grupo de edad se realizó el procesamiento de la información censal en el redatam.

Para medir la cobertura de los dispositivos de la población en estudio, se utilizan como medida de análisis los radios censales. En un primer momento, se realiza la unión de los polígonos con la información de la cantidad de adultos mayores de 65 años por radio censal. Luego se agrupan los radios censales según el peso que tenga esta población en niveles: alto, medio, bajo. Para esto se ordena la base por la cantidad de adultos mayores y se calculan los percentiles. Finalmente, se divide la base en tercios. Luego se georeferencian los vacunatorios y se arma una “zona de influencia” (buffer) de 500 metros de distancia para posteriormente realizar los análisis de cobertura por dispositivo y comuna. Este ejemplo presenta un alto grado de complejidad que se va ir desarrollando en los tres encuentros que le siguen. La idea es que podamos entre todos y todas ir desentrañando este pequeño proyecto. No queremos realizar algo con una previa manipulación, porque ustedes se van a encontrar con algunos de los “problemas” que vamos a ir superando entre todos.


2- ESTRUCTURA DE LOS DATOS

Como se mencionó en la introducción, se utilizó la información publicada en el portal Buenos Aires Data. De este repositorio se descarga la georreferencia de los vacunatorios utilizados para ampliar la capacidad del sector público y los polígonos de los radios censales y de las comunas. También se utiliza la información de la población adulta mayor a 65 años a nivel de radio censal del Cuestionario Básico del Censo. A continuación se realiza un desagregado de las variables a usar según las variables y fuentes.


Información Censal por Radio

Fuente: Dirección General de Estadísticas y Censos. Ministerio de Hacienda y Finanzas (GCBA)

Variable Observación Tipo de dato
Radios Censales Código de identificación de los radios censales elaborados por el INDEC Numérico
Barrio Barrios de la CABA Carácter
Comuna División Administrativa de la CABA Carácter
Geometría Polígonos de la CABA Espacial

Vacunatorios Adultos Mayores en Emergencia

Fuente: Ministerio de Salud (MSGC)

Variable Observación Tipo de dato
Nombre Nombre del vacunatorio Carácter
Barrio Barrios donde se ubican los vacunatorios de la CABA Carácter
Comuna División política y administrativa donde se ubican los vacunatorios de la CABA Carácter
Tipo Tipo de dispositivo para vacunar Carácter
Geometry Punto con la georreferencia Espacial

Centros de Salud de Acción Comunitaria (CeSAC)

Fuente: Ministerio de Salud (MSGC)

Variable Observación Tipo de dato
Nombre Nombre del CESAC Carácter
Barrio Barrios donde se ubica el CESAC Carácter
Comuna División política y administrativa donde se ubican los CESAC de la CABA Carácter
Tipo Tipo de dispositivo para vacunar Carácter
Geometry Punto con la georreferencia Espacial

Edades en Grandes Grupos

Fuente: Cuestionario Básico del Censo Nacional de Población, Hogares y Viviendas - 2010 (INDEC)

Variable Observación Tipo de dato
Radios Censales Código de identificación de los radios censales elaborados por el INDEC Carácter
Edad 65 Cantidad total de adultos mayores de 65 en el radio censal Numérico
Tolal poblacional Total de población en el radio censal Numérico


3- ACTIVIDADES DE PROCESAMIENTO

A continuación se realiza un desagregado de las actividades que se realizan en esta guía para responder al objetivo propuesto:

1. Limpieza y transformación de las tablas
2. Reconstrucción del ID de los radios censales
3. Unión de las tablas de edad y radios censales a partir del ID
4. Creación de la variable nivel de presencia de adultos mayores en el radio
5. Unión de filas del dataset de los vacunatorios con los CESACS
6. Cambio de proyección de coordenadas a metros de los datos espaciales de radios censales y vacunatorios
7. Construcción de las áreas de influencia usando buffers a 500 metros
8. Unión espacial entre los radios censales y los buffers utilizando como forma de unión la intersección
9. Identificación de los radios censales duplicados
10. Cálculo de la distancia entre radios censales y vacunatorios para evitar radios duplicados
11. Construcción del mapa de cobertura de los dispositivos de vacunación
12. Análisis con gráfico de barras de la cobertura por comuna según dispositivos

Bibliotecas a utilizar

### ACTIVAR BIBIBLIOTECAS
library(tidyverse)
library(sf)
library(httr)
library(readxl)
library(janitor)
library(kableExtra)



4- ¡A DESCARGAR LOS ARCHIVOS!

Previo a continuar, descargamos algunos archivos que nos van a permitir introducirnos en los datos espaciales. Es muy importante que hayas seteado el directorio para saber dónde se descargan los archivos. Una de las bondades que también nos permite R es poder descargar los archivos de las página web a través de escribir el código. Además podemos gestionar los archivos y carpetas locales. Es un nivel avanzado en el uso R. Pero es interesante porque nos ahorra ir hasta cada una de las páginas, descargar los archivos y descomprimirlos. Utilizamos esta forma porque son archivos comprimidos. Otros tipo de archivos directamente los podemos descargar a través del comando que utilizamos para cargarlos (más adelante vamos a ver unos ejemplos).

#--> Vacunatorios
URL_vacunatorios <- "https://cdn.buenosaires.gob.ar/datosabiertos/datasets/vacunatorios-adultos-mayores/vacunatorios-adultos-mayores.zip"
GET(URL_vacunatorios,  write_disk(paste0(getwd(),"/Vacunatorios.zip")))
## Response [https://cdn.buenosaires.gob.ar/datosabiertos/datasets/vacunatorios-adultos-mayores/vacunatorios-adultos-mayores.zip]
##   Date: 2021-03-02 15:44
##   Status: 200
##   Content-Type: application/zip
##   Size: 7.04 kB
## <ON DISK>  C:\Users\flavio\Desktop\Buceando R\Curso UNTREF\Encuentro IV\Vacunatorios.zip
unzip(zipfile = "Vacunatorios.zip",exdir = paste0(getwd(),"/Vacunas"))
file.remove("Vacunatorios.zip")
## [1] TRUE
#--> Radios Censales CABA
URL_radios <- "https://cdn.buenosaires.gob.ar/datosabiertos/datasets/informacion-censal-por-radio/informacion-censal-por-radio-2010.zip"
GET(URL_radios,  write_disk(paste0(getwd(),"/Radios.zip")))
## Response [https://cdn.buenosaires.gob.ar/datosabiertos/datasets/informacion-censal-por-radio/informacion-censal-por-radio-2010.zip]
##   Date: 2021-03-02 15:44
##   Status: 200
##   Content-Type: application/zip
##   Size: 634 kB
## <ON DISK>  C:\Users\flavio\Desktop\Buceando R\Curso UNTREF\Encuentro IV\Radios.zip
unzip(zipfile = "Radios.zip",exdir = paste0(getwd(),"/Radios Censales"))
file.remove("Radios.zip")
## [1] TRUE
#---> Edades CABA
URL_edades <- "https://github.com/flavioscargiali/desembarcandorensociales/raw/935278584c19dea2b35bd34f415dc91fe3b503aa/EdadCaba.zip"
GET(URL_edades,  write_disk(paste0(getwd(),"/Edades.zip"),overwrite = T))
## Response [https://raw.githubusercontent.com/flavioscargiali/desembarcandorensociales/935278584c19dea2b35bd34f415dc91fe3b503aa/EdadCaba.zip]
##   Date: 2021-03-02 15:44
##   Status: 200
##   Content-Type: application/zip
##   Size: 132 kB
## <ON DISK>  C:\Users\flavio\Desktop\Buceando R\Curso UNTREF\Encuentro IV\Edades.zip
unzip(zipfile = "Edades.zip",exdir = paste0(getwd(),"/Edades"))
file.remove("Edades/Edades.zip")
## [1] FALSE



5- CONOCIENDO SF

Para poder cumplir con el objetivo que nos propusimos se utiliza la biblioteca “simple features” (SF). Simple Features, además de dar nombre al paquete de R, es un estándar que se utiliza para describir cómo los objetos del mundo real pueden ser representados en las computadoras a través de la geometría espacial de esos objetos. Una “feature” se tiene que pensar como una cosa o un objeto del mundo real como un árbol o una construcción. También pueden ser la combinación de una serie de objetos como una ciudad o un bosque. Estos objetos tienen geometría que describen en dónde están localizados en el mundo. También tienen atributos que describen otras propiedades: como la altura, el color, el diámetro, etc. Por ejemplo, la geometría de un árbol puede ser la delimitación de su copa, de su tallo o el punto que indica su centro. Pero esto puede ir acompañados con otra información en la tabla como la especie, la altura, el diámetro, el estado, etc. De esta manera, este tipo de estándar permite entonces tener una misma tabla información espacial (a través de la geometría) e información no espacial (otros tipos de atributos).

Los principales elementos que se utilizan para representar los objetos en el mundo real son:

Tipo Definición
Puntos Geometría de dimensión cero que contiene un solo punto
Líneas Secuencia de puntos conectados por líneas rectas que no se intersecan; geometría unidimensional
Comuna División Administrativa de la CABA
Polígonos Figura geométrica plana y está compuesta por una secuencia finita de segmentos rectos consecutivos que encierran una región en el plano

La representación precisa de la posición de una entidad geográfica sobre la superficie terrestre presenta una gran complejidad. Recordemos que la Tierra no es una esfera perfecta sino que está “achatada” en los polos, generando dificultad en los cálculos para comparar posiciones y medir distancias. Además, esto se complica en la posibilidad de plasmar sobre el papel impreso, o en una pantalla, los rasgos geográficos que pertenecen a una superficie tridimensional esférica. Para esto existen, las proyecciones cartográficas que son un sistema de representación gráfica que establece una relación ordenada entre los puntos de la superficie curva de la Tierra y los de una superficie plana (mapa). Es una transformación matemática que permite convertir las coordenadas esféricas (tres dimensiones) de la superficie de la tierra a coordenadas planas (dos dimensiones), permitiendo así representar objetos tridimensionales en un espacio plano. Un sistema de coordenadas de referencia (CRS en inglés) define, con la ayuda de las coordenadas, cómo el mapa bidimensional proyectado se relaciona con lugares en la tierra a través de un datum geodésico.

Como se mencionó anteriormente el paquete que se utiliza para trabajar con los datos espaciales en R es SF. A continuación se presentan algunos tips importantes sobre cómo se organizan las funciones de este paquete. En este sentido, todos los nombres de las funciones está acompañada por el prefijo st_, que refiere en inglés a spatial types. Se implementan como datos nativos de R, utilizando estructuras de datos simples (listas, matriz, vector, tablas). El uso típico implica leer, manipular y escribir conjuntos de características, con atributos (datos no espaciales) y geometrías (datos espaciales).

Usualmente no trabajamos únicamente con las entidades geográficas (representación gráfica de la entidad), sino que además hacemos análisis con atributos (variables no espaciales). Estos dos elementos se juntan en este tipo de objetos sf (entidad simple). La siguiente función, que forma parte del paquete SF nos ayuda a leer la tabla de los vacunatorio del GCBA:

VacunatoriosGCBA <- st_read("Vacunas/vacunatorios-adultos-mayores.shp")
## Reading layer `vacunatorios-adultos-mayores' from data source `C:\Users\flavio\Desktop\Buceando R\Curso UNTREF\Encuentro IV\Vacunas\vacunatorios-adultos-mayores.shp' using driver `ESRI Shapefile'
## Simple feature collection with 80 features and 6 fields
## geometry type:  POINT
## dimension:      XY
## bbox:           xmin: -58.5253 ymin: -34.68989 xmax: -58.37062 ymax: -34.54537
## geographic CRS: WGS 84


Desentrañemos la función: st_read. Recordemos que el prefijo “st” refiere a “spatial type” y “read” traducido al español es “leer”. De esta manera, la función nos permite leer datos espaciales que responden a este estándar. Vemos que una vez que corrimos la función nos devuelve un resumen del objeto:

Tipo Definición
Reading layer
Simple feature collection with 80 features and 6 fields
La tabla está formada por 80 filas y 6 columnas.
Geometry type:
POINT
El tipo de entidad geométrica que se utilizan son puntos.
Dimension:
XY
La dimensiones que presentan los datos geográficos. En este caso, no se incluye información de alturas (dimensión Z).
bbox:
xmin: -58.5253 ymin: -34.68989 xmax: -58.37062 ymax: -34.54537
Cuatro valores que constituyen una “caja” (bounding box) que contiene todos los datos.
geographic CRS:
WGS 84
El tipo de sistema de coordenadas utilizada.

Revisemos el tipo de objeto que es la tabla que contiene la información sobre los vacunatorios:

class(VacunatoriosGCBA)
## [1] "sf"         "data.frame"


La función class() devuelve que nuestra tabla es un sf y un dataframe. Recordemos que trabajamos con atributos espaciales y no espaciales que se combinan en este tipo de objetos. Por último, a través de la función attr() identificamos la columna que contiene la información geográfica.

attr(VacunatoriosGCBA, "sf_column")
## [1] "geometry"


Para ampliar la información sobre este paque recomendamos que visites la página oficial del paquete y la “cheatsheet” con el resumen de las principales funciones.


6- MANOS A LA OBRA
6.1. Cargando Archivos

Como todo proyecto, empezamos con la carga de los archivos que se utilizan:

### CARGA DE LOS ARCHIVOS
#--> Carga de los archivos en el ambiente
RadiosCensales <- read_sf("Radios Censales/informacion_censal_por_radio_2010.shp")
VacunatoriosGCBA <- read_sf("Vacunas/vacunatorios-adultos-mayores.shp")

#--> Otra forma alternativa de cargar información espacial: .geojson
Comunas<-read_sf("https://cdn.buenosaires.gob.ar/datosabiertos/datasets/comunas/CABA_comunas.geojson")
Cesacs<-read_sf("https://cdn.buenosaires.gob.ar/datosabiertos/datasets/salud/centros-salud-accion-comunitaria-cesac/centros_de_salud_nivel_1_BADATA_WGS84.geojson")

#--> Carga de excel
Edades <- read_excel("Edades/EdadCaba.xlsx")



6.2. Un caso real

Muchas veces nos encontramos con tablas que tienen algunas dificultades para ser utilizadas en el procesamiento con r. La tabla edades y RadiosCensales presentan una serie de dificultades que iremos superando en esta guía. Como ejercicio les proponemos que abran los archivos y revisen esas dificultades. Para acomodar las tablas y variables a los requerimientos de r vamos a utilizar una serie de funciones que la mayoría de ellas se presentaron anteriormente. Empecemos por la tabla de edades. En este caso, tenemos un encabezado con información en las primeras filas y un símbolo (-) en las variables que nos impiden realizar cálculos. Veamos el código para “arreglar” la tabla edades:

# --> Limpieza de la tabla 
Edades <- Edades %>% 
  slice(15:3568) %>% # <--- Recortar la tabla
  row_to_names(1) %>% # <--- Trasladar la primera fila al encabezado
  select(-1) %>%  # <--- Sacar la primera columna 
  mutate_all(~str_replace_all(.,"-","0")) %>% # <--- Sustituir - por 0
  mutate_at(-1, ~as.numeric(.)) %>% # <--- Transformar todas las variables a excepción de la primera en numérica
  rename(Link = 1, 
         E014 = 2,
         E1564 = 3,
         E65 = 4,
         TotPob = 5) # <--- Renombrar las variables 


A continuación realizamos también una transformación de datos en la tabla que contiene las entidades geográficas de los radios censales. Se aclara que en este tipo de archivos se pueden utilizar las funciones de manipulación y transformación que se vieron en el curso. En este caso, tenemos que corregir el ID de los radios censales para poder unir con la tabla de edades. Para consultar los códigos definidos por el INDEC (ID) para los radios censales les compartimos el documento https://redatam.indec.gob.ar/redarg/CENSOS/CPV2010A/Docs/codigos_provincias.pdf

# --> Ordenando la tabla: modificando el id erróneo
RadiosCensales<-RadiosCensales %>% 
  separate(col = RADIO_I,into = c("COM","LOC","RAD")) %>% # <--- Separar la columna Radio a partir del símbolo “-”  
  mutate_at(.vars = vars(1:3),~as.numeric(.)) %>% 
  mutate(Link=paste0("2",substr(as.character(1000+COM),2,4),
                     substr(as.character(100+LOC),2,3),
                     substr(as.character(100+RAD),2,3))) # <--- Reconstruir el ID de los radios



6.3. Radios censales por edad

Una vez que “acomodamos” la información de nuestras tablas podemos avanzar con la unión. Para esto, utilizamos la función left_join() del paquete dplyr y la columna “link” como campos compartidos por las dos tablas.

#Unión de las tablas 
RadiosCensales<-left_join(RadiosCensales, Edades, by=("Link")) %>% 
  select(12,4:10,13:16,11) # <--- Selección de algunas variables



6.4. Construyendo variables

Construimos un indicador cualitativo para medir la presencia de adultos mayores en los radios censales. Para esto utilizamos la tabla que unimos anteriormente. Para la construcción ordenamos la tabla de menor a mayor por la variable de “edad mayor a 65 años” y calculamos de manera aproximada los percentiles. Una vez que realizamos esto dividimos la variable en tercios. Creamos la variable “nivel de adultos mayores” a través de usar condiciones:

  • Si pertenece al primer tercio creamos la categoría: Bajo
  • SI pertenece al segundo tercio creamos la categoría: Medio
  • Si pertenece al tercer tercio creamos la categoría: Alto
# --> Percentil: Alto, Medio, Bajo
RadiosCensales <- RadiosCensales %>%
  mutate(E65 = replace_na(E65,0)) %>% # <--- Reemplazar valores perdidos
  arrange(E65) %>% # <--- Ordenar la tabla de menor a mayor
  mutate(Percentil = cumsum(E65)/sum(E65)*100, # <--- Calcular los percentiles
         GE65 = ifelse(Percentil<33.3,"Bajo",
                     ifelse(Percentil>= 33.3 & Percentil<66.6, "Medio",
                            "Alto"))) # <--- Construcción de la variable nivel de adultos mayores



6.5. Transformando proyecciones

Para realizar los análisis espaciales cambiamos la proyección que está en grados a metros. Utilizamos la función st_transform para cambiar la proyección de nuestras entidades geográficas.

#--> Transformar las proyecciones de grados a metros
RadiosCensales <- st_transform(RadiosCensales, crs = 3857)
VacunatoriosGCBA <- st_transform(VacunatoriosGCBA, crs = 3857)
Cesacs <- st_transform(Cesacs, crs = 3857)


6.6. Uniendo vacunatorios

Para ordenar la información agrupamos los vacunatorios creados en emergencia por GCBA con los CeSACS. Para poder “pegar” los registros de la tabla Cesacs con los de VacunatoriosGCBA utilizamos bind_rows(). Esta función pone de limitante que las columnas de ambas tablas deben llamarse iguales, tener el mismo orden y ser del mismo tipo.

#--> Agrego los cesacs como puntos de vacunatorios

Cesacs<-Cesacs %>% 
  mutate(tipo= "CESAC", COMUNAS=as.character(COMUNAS)) %>% # <--- Transformar a caracter
  select(nom_ante, BARRIO, COMUNAS, tipo, calle2, area_progr ) %>% # <--- Seleccionar algunas variables
  rename(nombre=1, barrio=2, comuna=3, domicilio=5, aph=6) # <--- Renombrar las variables

VacunatoriosGCBA<-bind_rows(VacunatoriosGCBA, Cesacs) # <--- Unir las filas de los Cesacs con la de los vacunatorios


Para ver el resultado, realizamos un gráfico de los vacunatorios (incluidos los CeSACS):

#--> Representación gráfica de los vacunatorios en el mapa
ggplot()+
  geom_sf(data=RadiosCensales) + # <--- Agregar los polígonos de los radios censales
  geom_sf(data=VacunatoriosGCBA, aes(color=tipo)) # <--- Agregar los puntos de los vacunatorios y colorear según el tipo de dispositivo



6.7. Armando zonas de influencia

Como se mencionó en el objetivo de esta guía, proponemos analizar la cobertura de los vacunatorios de emergencia en la población de mayores de 65 años. Para esto, vamos a construir “zonas de influencias” utilizando la función st_buffer. Esta función permite crear un polígono que enmarca el área de influencia a una distancia específica alrededor del punto de los vacunatorios. Por esto anteriormente realizamos la transformación de la proyección a metros. A continuación, se genera un área de influencia de 500 metros de distancia con respecto al vacunatorio.

#--> Representación de buffer
Vacunatorios500m<-st_buffer(VacunatoriosGCBA, 500) # <--- Armado de la zona de influencia


Visualizamos las zonas de influencias.

ggplot()+
  geom_sf(data=RadiosCensales) + 
  geom_sf(data=Vacunatorios500m, aes(fill=tipo))+ # <--- Agregrar las zonas de influencia de los vacunatorios
  geom_sf(data=VacunatoriosGCBA, color="white")



6.8. Cobertura de los vacunatorios

Para poder evaluar la cobertura de la población en estudio, se avanza con una unión espacial para analizar los radios censales que son alcanzados por esta política. Se utiliza la función st_join para realizar esa unión y quedarnos con los radios censales que son intersectados por la “zona de influencia” de los vacunatorios.

#--> Unión de tablas: radios interceptados por los vacunatorios 
RadVac<-st_join(
  RadiosCensales,
  Vacunatorios500m%>% st_as_sf(),
  join = st_intersects) %>% # <--- Unión espacial usando como método de unión st_intersects
  filter(!is.na(nombre)) %>% 
  arrange(Link) # <--- IMPORTANTE ordenar la base para una futura operación

#--> Gráfico del resultado
ggplot()+
  geom_sf(data=RadVac)+
  geom_sf(data=Vacunatorios500m, aes(fill=tipo))+
  geom_sf(data=VacunatoriosGCBA, color="white")


Pero acá hay un problema. ¿Se imaginan cuál es?

Lo que sucede es que un radio censal puede estar interceptado por más de una zona de influencia lo que produciría una duplicación de esa población. Veamos qué radios están duplicados y cuantas veces:

RadVac %>% 
  group_by(Link) %>% 
  summarise(Cantidad = n()) %>%  
  filter(Cantidad > 1)
## Simple feature collection with 560 features and 2 fields
## geometry type:  MULTIPOLYGON
## dimension:      XY
## bbox:           xmin: -6514579 ymin: -4122136 xmax: -6495553 ymax: -4102420
## projected CRS:  WGS 84 / Pseudo-Mercator
## # A tibble: 560 x 3
##    Link     Cantidad                                                    geometry
##  * <chr>       <int>                                          <MULTIPOLYGON [m]>
##  1 20010101        2 (((-6497929 -4108572, -6497943 -4108567, -6497944 -4108590~
##  2 20010204        2 (((-6499314 -4107015, -6499331 -4107003, -6499410 -4106955~
##  3 20010206        2 (((-6499063 -4107253, -6499077 -4107265, -6499162 -4107217~
##  4 20010207        2 (((-6499019 -4107194, -6498888 -4107268, -6498720 -4107356~
##  5 20010208        2 (((-6498955 -4107323, -6498948 -4107313, -6498928 -4107293~
##  6 20010209        2 (((-6498763 -4107438, -6498757 -4107442, -6498732 -4107457~
##  7 20010210        2 (((-6498659 -4107507, -6498690 -4107481, -6498732 -4107457~
##  8 20010211        3 (((-6498709 -4107361, -6498682 -4107327, -6498674 -4107313~
##  9 20010212        3 (((-6498831 -4107186, -6498831 -4107177, -6498749 -4107055~
## 10 20010213        2 (((-6498515 -4107516, -6498530 -4107504, -6498605 -4107457~
## # ... with 550 more rows


Podríamos aplicar una función para quedarnos con los valores únicos de algunas de las variables pero esto perjudica nuestra precisión del análisis. Para superar este obstáculo realizamos una operación espacial para medir la distancia en metros de los vacunatorios con los radios. Se van a concretar los siguientes pasos:

  1. Obtener los vacunatorios que interceptan los radios (proceso inverso al que realizamos) y ordenar la tabla por el ID de los radios
  2. Utilizar la función mapply() para calcular la distancia (st_distance) de los puntos geográficos contenidos en dos tablas diferentes. Para esto, la función compara la fila de una tabla con la fila de la otra.
  3. Finalmente, pegamos con cbind() la distancia calculada a los radios que interceptan los vacunatorios (RadVac), agrupamos por radios (group_by y retenemos la distancia mínima.

Veamos el código:

# <--- Retenemos los puntos de los vacunatorios interceptado por los radios. Proceso inverso a RadVac
VacRad<-st_join(
  Vacunatorios500m %>% st_as_sf(),
  RadiosCensales,
  join = st_intersects) %>% 
  st_centroid() %>% 
  filter(!is.na(nombre)) %>% 
  arrange(Link)

#--> Cálculo de distancia entre los vacunatorios y los radios
RadVacDist<-st_geometry(RadVac); VacRadDist<-st_geometry(VacRad)
Dist<-mapply(st_distance, RadVacDist, VacRadDist) # <--- Comparar fila con fila

#--> Distancia de cada radio con los vacunatorios para ver la cobertura
RadVacDis<-RadVac %>% 
  cbind(Dist) %>% # <--- Pegar la distancia
  group_by(Link) %>% # <--- Agrupar por los códigos de los radios censales
  slice(which.min(Dist)) # <-- Filtrar por la distancia mínima


Veamos si quedaron algunos radios duplicados:

RadVacDis %>% 
  group_by(Link) %>% 
  summarise(Cantidad = n()) %>%  
  filter(Cantidad > 1)
## Simple feature collection with 0 features and 2 fields
## bbox:           xmin: NA ymin: NA xmax: NA ymax: NA
## projected CRS:  WGS 84 / Pseudo-Mercator
## # A tibble: 0 x 3
## # ... with 3 variables: Link <chr>, Cantidad <int>, geometry <GEOMETRY [m]>

Para futuros análisis, generamos también una tabla incorporando los radios sin cobertura de los vacunatorios. En la próxima sección se retoma esta tabla para “conocer ggplot”.

#--> Sin cobertura
RadSc<-st_join(
  RadiosCensales,
  Vacunatorios500m%>% st_as_sf(),
  join = st_intersects) %>% 
  filter(is.na(nombre)) %>% 
  mutate(Dist=NA)

#--> Unimos la tabla de cobertura con sin cobertura
AnaVac<-rbind(RadVacDis, RadSc)

#--> Seleccionamos algunas variables y nos desprendemos de la geometría
AnaVac<-AnaVac %>% 
  select(Link, BARRIO, COMUNA, E014, E1564, E65, TotPob, Percentil, GE65, nombre, barrio, comuna, tipo) %>% 
  rename(Barrio = 2, Comuna = 3, VacNombre = 10, VacBarrio=11, VacComuna=12, VacTipo=13) %>% 
  st_drop_geometry()

#--> Guardamos la tabla para futuros análisis 
write.csv(AnaVac, paste0(getwd(),"/Vacunatorios.csv"))


Finalmente, realizamos un gráfico para observar la cobertura de los vacunatorios del GCBA.

#--> Gráfico con los radios con cobertura
InfVac<-RadVacDis %>% 
  group_by(nombre, tipo) %>% # <--- Agrupamos para ver la zonas de influencia de cada vacunatorio
  summarise() %>% 
  mutate(Cobertura="Vacunatorio a 500 metros") 


color<-c("#cf3b2d","#e48f73","#fbdad1")

ggplot()+
  geom_sf(data = RadiosCensales, aes(fill=GE65), color = NA)+ # <--- Poligonos de los radios con relleno GE65
  geom_sf(data = InfVac,aes(color=Cobertura), size=0.8, alpha=0.4, fill="#556270")+  #<--- Cobertura de los vacunatorios
  scale_color_manual("Cobertura",values="black")+
  geom_sf(data = Comunas, fill=NA, color="black")+
  scale_fill_manual("Pob. adulta mayor",values=color, breaks=c("Alto","Medio","Bajo"))+
  theme_void()+
  labs(title = str_wrap("Radios Censales según adultos mayores por cobertura de vacunatorio en Centro de día",70),
       subtitle = "Campaña antigripal 2020 - CABA",
       caption = "Fuente: Buenos Aires Data - INDEC Censo Nacional de Población")

Por último, graficamos la cobertura de los radios según el tipo de dispositivo de vacunación

ggplot()+
  geom_sf(data = RadiosCensales)+
  geom_sf(data = InfVac,aes(color=tipo, fill=tipo), size=0.8, alpha=0.4)+
  geom_sf(data = Comunas, fill=NA, color="black")+
  theme_void()+
  labs(title = str_wrap("Radios Censales según cobertura de dispositivos",70),
       subtitle = "Campaña antigripal 2020 - CABA",
       caption = "Fuente: Buenos Aires Data - INDEC Censo Nacional de Población")



6.9. Machete SF

Por último, compartimos una “cheatsheet” que resume los principales puntos de SF.



7- CONOCIENDO GGPLOT


7.1. Introducción


El 10 de junio de 2007 ocurrió un gran acontecimiento que marcó el comienzo de una nueva forma de concebir la visualización de datos. Ese día, el desarrollador y estadístico, Hadley Wickam publicó un paquete de fundamental importancia en el mundo de R: ggplot.

A partir de ese momento, el paquete fue ganando terreno alcanzando millones y millones de descargas. Pero, ¿qué significa ggplot? Es la combinación gg y plot. El prefijo gghace referencia a la “gramática de los gráficos”. Todavía seguimos en un nivel de abstracción muy alto. Se entiende por gramática a la parte de la lingüística que estudia la estructura de las palabras y sus accidentes, así como la manera en que se combinan para formar oraciones; incluye la morfología y la sintaxis. De esta manera, aplican, ggplot se comprende como una estructura de palabras que se combinan para permitirnos realizar diferentes y variadas representaciones gráficas a través del uso del lenguaje R.

Por su parte plot, además de su traducción del inglés al español como gráfico, nos gusta entenderlo con otro de sus significados: “trama”. El origen de esta palabra hace referencia al conjunto de hilos que, combinados y enlazados entre sí, consigue darle forma a una tela, De manera sencilla, ggplot nos proporciona un conjunto de funciones que se combinan para formar una representación gráfica. Vayamos a conocer la potencialidad de este paquete a través de la práctica.

Como ejemplo se analiza la cobertura de la campaña de vacunación antigripal en la Ciudad Autónoma de Buenos Aires por comuna y dispositivo de aplicación. A continuación se hace un desagregado de las actividades a realizar en este módulo.
1. Activación de bibliotecas y carga de datos
2. Gráfico boxplot
3. Gráfico de dispersión
4. Gráfico de barras
5. Gráfico de coordenadas polar


7.2. Carga de datos


anavac <- read_csv("https://raw.githubusercontent.com/flavioscargiali/desembarcandorensociales/master/Vacunatorios.csv", locale = locale(encoding = "latin1"))
library(tidyverse)
library(RColorBrewer)

colourCount <- length(unique(anavac$Comuna))
getPalette <- colorRampPalette(brewer.pal(9, "Set3"))

anavac <- read_csv("https://raw.githubusercontent.com/flavioscargiali/desembarcandorensociales/master/Vacunatorios.csv", locale = locale(encoding = "latin1"))


7.3. Gráfico de diagrama de caja

El primer gráfico que vamos a utilizar es el box plot o diagrama de caja, que es un método estandarizado para representar gráficamente una serie de datos numéricos a través de sus cuartiles. De esta manera, el gráfico muestra a simple vista la mediana y los cuartiles de los datos, pudiendo también representar los valores atípicos de estos. A continuación se presentan en la imagen los elementos de un gráfico de este tipo:

Pero, ¿cómo hacemos para construir este tipo de gráfico? A través del paquete ggplot. Previo a esto vamos a realizar una pequeña transformación de datos:

VacExp <- anavac %>%
  arrange(Comuna) %>% # <-- Ordenamos la base
  mutate(VacTipo = replace_na(VacTipo,"Sin Cobertura"), #<--- Reemplazamos valores nulos
         Comuna = paste0("Comuna ", Comuna), #<--- Agregamos la palabra “Comuna”
         Comuna = factor(Comuna,levels = paste0("Comuna ", seq(1:15)))) %>%  #<---Creamos los factores
  filter(VacTipo == "Sin Cobertura") #<--- Filtramos los que no tienen cobertura 

Una vez realizada la transformación, la intención es analizar la distribución en los cuartiles de la cantidad de personas mayores a 65 años que no tuvieron un vacunatorio cerca (5 cuadras) de su radio censal.

ggplot(data = VacExp, aes(x = Comuna, y = E65, fill=Comuna))

Pero… , ¿qué sucedió? ¿Por qué sólo aparecen los ejes? ggplot() permite construir un objeto ggplot, es decir una representación gráfica, pero falta agregar todas las especificaciones. Puede ser utilizada para declarar la tabla que vayamos a utilizar y para detallar el conjunto de especificaciones estéticas que son comunes a todos las subsecuentes capas amenos que se especifiquen otros criterios. ggplot() utiliza el + para agregar los diferentes componentes del gráfico. Se destaca que estos tipos de objetos funcionan por capas. Cuando veamos el ejemplo va a quedar más claro. Según la documentación de esta función hay tres maneras distintas de invocar a ggplot.

- ggplot(df, aes(x, y, other aesthetics)): se recomienda si todas las capas usan la misma tabla y los mismos criterios estéticos. También, se pueden agregar capas usando datos de otra tabla.
- ggplot(df): este tipo de invocación específica la tabla a usar para el gráfico pero no los detalles estéticos. Este tipo es utilizado cuando se utiliza una tabla de manera predominante pero los criterios estéticos pueden variar de una capa a la otra.
- ggplot(): se usa para iniciar un “esqueleto” de un objeto ggplot a la que se le agregan las diferentes capas. Es recomendable utilizar cuando utilizamos múltiples tablas para producir diferentes capas.

A modo sencillo, siempre que corramos únicamente la función ggplot() sin ninguna otra capa, devuelve el “lienzo” sobre el que va a representar la información. El arte aparece cuando agregamos las sucesivas capas. Sin embargo, especificamos a R que la tabla que utilizamos se llama “VacExp”, el gráfico está formado por un eje X formado por el nombre de las comunas, un eje Y con la cantidad de personas mayores de 65 años en el radio y censal, y un “relleno” a partir de la variable comunas. Sin embargo, no detalla el tipo de gráfico que queremos. Esto lo hacemos, agregando a nuestra línea de código inicial una capa con la función geom_box() para armar nuestro diagrama de caja. Recuerde que para concatenar las capas no sirve el pipe (%>%), se utiliza el signo +.

ggplot(data = VacExp, aes(x = Comuna, y = E65, fill=Comuna)) +
  geom_boxplot() # <--- Indicamos el tipo de gráfico

Finalmente apareció el diagrama, pero todavía no es una visualización que ayude a interpretar la información. Como primera medida, cambiamos de lugar el eje X e Y para hacer más legible la visualización. Para esto usamos la función coord_flip()

Para seguir completando nuestro gráfico, agregamos la posición de cada radio censal de acuerdo a la cantidad de adultos mayores con la función geom_jitter(). A través de esta capa podemos graficar los puntos de los radios censales sin que se superpongan.

ggplot(data = VacExp, aes(x = Comuna, y = E65, fill=Comuna)) +
  geom_boxplot() +
  geom_jitter(color="grey", size=0.7, alpha=0.5) # <--- agregamos criterios estéticos  coord_flip()

Para mejorar los puntos, agregamos algunos criterios estéticos dentro de geom_jitter(): el color, el tamaño y la transparencia de los puntos. Para continuar, se adicionan el nombre de los ejes X e Y, el título y la fuente.

ggplot(data = VacExp, aes(x = Comuna, y = E65, fill=Comuna)) +
  geom_boxplot() +
  geom_jitter(color="grey", size=0.7, alpha=0.5) +
  ylab("Individuos") + # <--- agregamos el nombre del eje X
  xlab("Comunas") + # <--- agregamos el nombre del eje X
  labs(title = "Radios según población de E65 sin cobertura de vacunatorios por Comunas", 
       caption = "Fuente: elaborado en base a datos de MSGC e INDEC")+ # <--- agregamos el título y la fuente 
  coord_flip() # <--- cambiamos de lugar el X e Y

Una forma de mejorar la visualización, es agregando un tema predefinido o modificando elementos de los temas. En el primer caso, usamos la función theme_minimal() que cambia la apariencia del gráfico. También, quitamos la leyenda y cambiamos el tamaño de la letra del título.

ggplot(data = VacExp, aes(x = Comuna, y = E65, fill=Comuna)) +
  geom_boxplot() +
  geom_jitter(color="grey", size=0.7, alpha=0.5) +
  ylab("Individuos") +
  xlab("Comunas") +
  labs(title = "Radios según población de E65 sin cobertura de vacunatorios por Comunas",
       caption = "Fuente: elaborado en base a datos de MSGC e INDEC") + # <--- Agregamos el título y la fuente
  theme_minimal() + # <--- Agregamos un tema predefinido
  theme(
    legend.position="none",
    plot.title = element_text(size=11)) +
  coord_flip()

Como uno de los últimos pasos, modificamos el color de relleno de las escala con la capa scale_fill_manual().

ggplot(data = VacExp, aes(x = Comuna, y = E65, fill=Comuna)) +
  geom_boxplot() +
  geom_jitter(color="grey", size=0.7, alpha=0.5) +
  theme_minimal() +
  theme(
    legend.position="none",
    plot.title = element_text(size=11)
  ) +
  ylab("Individuos")+
  xlab("Comunas")+
  labs(title = "Radios según población de E65 sin cobertura de vacunatorios por Comunas",
       caption = "Fuente: elaborado en base a datos de MSGC e INDEC")+
  coord_flip()+
  scale_fill_manual("Comuna", values = getPalette(colourCount)) # <--- Cambiamos la escala de relleno


Por último, cambiamos la escala del eje Y indicando los valores mínimos/máximos y los intervalos utilizando la función scale_y_continuos()

ggplot(data = VacExp, aes(x = Comuna, y = E65, fill=Comuna)) +
  geom_boxplot() +
  geom_jitter(color="grey", size=0.7, alpha=0.5) +
  theme_minimal() +
  theme(
    legend.position="none",
    plot.title = element_text(size=11)
  ) +
  ylab("Individuos")+
  xlab("Comunas")+
  labs(title = "Radios según población de E65 sin cobertura de vacunatorios por Comunas",
       caption = "Fuente: elaborado en base a datos de MSGC e INDEC")+
  coord_flip()+
  scale_fill_manual("Comuna", values = getPalette(colourCount))+
  scale_y_continuous(limits = c(0, 600),
                     breaks = c(seq(0,600,by=50))) # <--- Modificamos el intervalo de la escala Y



En las próximas secciones presentamos otros tipos de visualización.



7.4. Gráfico de barras

Otro gráfico de mucho uso es el de barra. A continuación realizamos una transformación de datos para ajustar los valores a nuestra representación. En este caso, se plasma en el gráfico el porcentaje de población de mayores de 65 años que viven en un radio censal sin cobertura de la campaña antigripal.

VacBar <- anavac %>% 
  group_by(Comuna, Barrio, VacTipo) %>%  
  summarise(TotVac = sum(E65)) %>%
  mutate(VacTipo = replace_na(VacTipo,"Sin Cobertura"),
         TotVac = replace_na(TotVac, 0),
         PorVac = TotVac/sum(TotVac)*100,
         Comuna = paste0("Comuna ", Comuna),
         Comuna = factor(Comuna,levels = paste0("Comuna ", seq(1:15)))) %>% 
  filter(VacTipo == "Sin Cobertura")

Algo interesante se presenta en la estructura “gramatical” para armar este tipo de visualizaciones. Siempre partimos de un conjunto de datos y agregamos capas con los diferentes componentes esteticos. Si comparan con la información de la visualización anterior se van a encontrar con un montón de similitudes. En este caso punto usamos geom_col() porque nuestra intención es realizar un gráfico de barras.

ggplot(data = VacBar, aes( x = reorder(factor(Barrio), PorVac, sum), y = PorVac, fill = factor(Comuna))) +
  geom_col(color="black") + #<--- Capa con el gráfico de barras (color hace referencia al contorno de las barras)
  scale_fill_manual("Comuna", values = getPalette(colourCount)) + # <--- Colores de rellenos a partir de la variable "Comuna"
  scale_y_continuous(limits = c(0, 100),
                     breaks = c(seq(0,100,by=5))) + # <--- Escala de valores y quiebres del eje Y 
  coord_flip() + # <--- Cambiamos de lugar el eje X e Y
  ylab("Individuos (%)") + # <--- Nombre del eje Y
  xlab("Barrios") + # <--- Nombre del eje X
  labs(title = "Barrios según población sin cobertura de vacunatorios por Comunas",
       caption = "Fuente: elaborado en base a datos de MSGC e INDEC")+
  theme_minimal() # <--- Utilizamos un tema predefinido



7.5. Gráfico de coordenadas polares

Una de las cosas que ayudó a Wickham a desarrollar el paquete ggplot se vinculó en la búsqueda de similitudes y diferencias entre gráficos. Este autor trabaja una idea principal que da “vida” al paquete ggplot: el gráfico de torta es un gráfico de barras dibujados en coordenadas polares. A modo simple, estos gráficos parecen muy diferentes pero en términos de gramática tienen un montón de similitudes. Posterior a la transformación de datos para ajustarlos a nuestra visualización, mostramos un ejemplo de gráfico de torta.

VacCor <- anavac %>% 
  group_by(Comuna, VacTipo) %>%  
  summarise(TotVac = sum(E65)) %>%
  mutate(VacTipo = replace_na(VacTipo,"Sin Cobertura"),
         TotVac = replace_na(TotVac, 0),
         PorVac = TotVac/sum(TotVac)*100,
         Comuna = paste0("Comuna ", Comuna),
         Comuna = factor(Comuna,levels = paste0("Comuna ", seq(1:15))))


A continuación se presenta un ejemplo de gráfico en coordenadas polares para hacer visibles las semejanzas y diferencias con el gráfico de barras.


ggplot(data = VacCor, aes( x = VacTipo, y = PorVac, fill = factor(VacTipo))) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  scale_fill_manual("Comuna", values = getPalette(colourCount))+
  scale_y_continuous(limits = c(0, 100),
                     breaks = c(seq(0,100,by=10))) + 
  ylab("Individuos (%)")+
  xlab("")+
  labs(title = "Población según tipo de cobertura de vacunatorios  por Comunas",
       caption = "Fuente: elaborado en base a datos de MSGC e INDEC")+
    facet_wrap(~Comuna, ncol = 5) +
  theme_minimal()+
  theme(axis.title.y=element_blank(),
        axis.text.y=element_blank(),
        strip.background = element_rect(fill="#273746"),
        strip.text = element_text(colour = 'white',face = "bold"),
        legend.position = "top")


7.6. Machetes GGPLOT

Por último, compartimos una “cheatsheet” que resume los principales puntos de este hermoso paquete.