En este trabajo analizaremos datos relativos a la cobertura hospitalaria en la Ciudad de Buenos Aires. Para ello utilizaremos tres datasets espaciales del portal de datos abiertos del GCBA.

1.Importación y exploración de datos

Comenzamos como siempre, activando los paquetes que utilizaremos para explorar, transformar y visualizar estos datos. En este caso, estaremos utilizando “tidyverse”, “sf” y “ggmap”:

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.3     ✓ purrr   0.3.4
## ✓ tibble  3.1.0     ✓ dplyr   1.0.5
## ✓ tidyr   1.1.3     ✓ stringr 1.4.0
## ✓ readr   1.4.0     ✓ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(sf)
## Linking to GEOS 3.8.1, GDAL 3.1.4, PROJ 6.3.1
library(ggmap)
## Google's Terms of Service: https://cloud.google.com/maps-platform/terms/.
## Please cite ggmap if you use it! See citation("ggmap") for details.

A continuación, procederemos a importar y explorar la estructura de los tres sets de datos espaciales con los que vamos a trabajar.

barrios_caba <- st_read("data/barrios_caba.geojson")
## Reading layer `barrios_badata' from data source `/Users/nahuel/Desktop/hospitales/data/barrios_caba.geojson' using driver `GeoJSON'
## Simple feature collection with 48 features and 4 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: -58.53152 ymin: -34.70529 xmax: -58.33515 ymax: -34.52649
## Geodetic CRS:  WGS 84
str(barrios_caba)
## Classes 'sf' and 'data.frame':   48 obs. of  5 variables:
##  $ barrio   : chr  "CHACARITA" "PATERNAL" "VILLA CRESPO" "VILLA DEL PARQUE" ...
##  $ comuna   : int  15 15 15 11 5 6 11 10 10 7 ...
##  $ perimetro: num  7725 7088 8132 7705 8538 ...
##  $ area     : num  3115707 2229829 3615978 3399596 4050752 ...
##  $ geometry :sfc_POLYGON of length 48; first list element: List of 1
##   ..$ : num [1:142, 1:2] -58.5 -58.5 -58.5 -58.5 -58.5 ...
##   ..- attr(*, "class")= chr [1:3] "XY" "POLYGON" "sfg"
##  - attr(*, "sf_column")= chr "geometry"
##  - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA
##   ..- attr(*, "names")= chr [1:4] "barrio" "comuna" "perimetro" "area"
hospitales <- st_read("data/hospitales.geojson")
## Reading layer `hospitales_gcba_WGS84' from data source `/Users/nahuel/Desktop/hospitales/data/hospitales.geojson' using driver `GeoJSON'
## Simple feature collection with 36 features and 19 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -58.51563 ymin: -34.67185 xmax: -58.36012 ymax: -34.5539
## Geodetic CRS:  WGS 84
str(hospitales)
## Classes 'sf' and 'data.frame':   36 obs. of  20 variables:
##  $ ID        : num  1 2 4 6 7 8 9 10 11 12 ...
##  $ NOMBRE    : chr  "HOSPITAL GENERAL DE NIÑOS PEDRO DE ELIZALDE" "HOSPITAL GENERAL DE NIÑOS RICARDO GUTIERREZ" "HOSPITAL DE ODONTOLOGIA DR. RAMON CARRILLO (EX NACIONAL)" "HOSPITAL DE SALUD MENTAL BRAULIO MOYANO" ...
##  $ NOM_MAP   : chr  "HOSP. DE ELIZALDE" "HOSP. GUTIERREZ" "HOSP. ODONTOLOGICO CARRILLO" "HOSP. MOYANO" ...
##  $ OBJETO    : chr  "HOSPITAL" "HOSPITAL" "HOSPITAL" "HOSPITAL" ...
##  $ CALLE     : chr  "MANUEL A. MONTES DE OCA" "GALLO" "SANCHEZ DE BUSTAMANTE" "BRANDSEN" ...
##  $ ALTURA    : chr  "40" "1330" "2529" "2570" ...
##  $ DOM_NORMA : chr  "MONTES DE OCA, MANUEL AV. 40" "GALLO 1330" "SANCHEZ DE BUSTAMANTE 2529" "BRANDSEN 2570" ...
##  $ DOM_GEO   : chr  "40 MONTES DE OCA, MANUEL AV." "1330 GALLO" "2529 SANCHEZ DE BUSTAMANTE" "2570 BRANDSEN" ...
##  $ TELEFONO  : chr  "4307-5842 / 5844" "4962-9247 / 9248 / 9280" "4805-5521 / 7533" "4301-3655 / 3659" ...
##  $ GUARDIA   : chr  "4307-5442 / 4300-1700" "4962-9232" "4805-6407" "4301-4522" ...
##  $ FAX       : chr  "4302-7400" "4962-3762" "4805-7533" "4303-3655/59" ...
##  $ WEB       : chr  "www.elizalde.gov.ar" "www.guti.gov.ar" NA "www.moyano.org.ar" ...
##  $ COD_POSTAL: chr  "C1270AAN" "C1425EFD" "C1425DUY" "C1287ABJ" ...
##  $ TIPO      : chr  "Hospital de niños" "Hospital de niños" "Hospital especializado" "Hospital especializado" ...
##  $ TIPO_ESPEC: chr  "PEDIATRIA" "PEDIATRIA" "ODONTOLOGIA" "SALUD MENTAL" ...
##  $ MOD_AT_1  : chr  "AT. AMB./INTERNACION" "AT. AMB./INTERNACION" "AT. AMBULATORIA" "AT. AMB./INTERNACION" ...
##  $ MOD_AT_2  : chr  "DIAG./TRATAM." "DIAG./TRATAM." "DIAG./TRATAM." "DIAG./TRATAM." ...
##  $ DEPEND_ADM: chr  "Ministerio de Salud GCBA" "Ministerio de Salud GCBA" "Ministerio de Salud GCBA" "Ministerio de Salud GCBA" ...
##  $ DIRECTOR  : chr  "Dr. Javier Indart" "Dra. María Cristina Galoppo" "Dra. Susana Rita Lisanti" "Dra. Norma Derito" ...
##  $ geometry  :sfc_POINT of length 36; first list element:  'XY' num  -58.4 -34.6
##  - attr(*, "sf_column")= chr "geometry"
##  - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA NA ...
##   ..- attr(*, "names")= chr [1:19] "ID" "NOMBRE" "NOM_MAP" "OBJETO" ...
datos_censales_xradio <- st_read("data/caba_radios_censales.geojson")
## Reading layer `CABA_rc' from data source `/Users/nahuel/Desktop/hospitales/data/caba_radios_censales.geojson' using driver `GeoJSON'
## Simple feature collection with 3554 features and 8 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -58.53092 ymin: -34.70574 xmax: -58.33455 ymax: -34.528
## Geodetic CRS:  WGS 84
str(datos_censales_xradio)
## Classes 'sf' and 'data.frame':   3554 obs. of  9 variables:
##  $ RADIO_ID   : chr  "1_1_1" "1_12_1" "1_12_10" "1_12_11" ...
##  $ BARRIO     : chr  "RETIRO" "SAN NICOLAS" "SAN NICOLAS" "SAN NICOLAS" ...
##  $ COMUNA     : chr  "1" "1" "1" "1" ...
##  $ POBLACION  : num  336 341 296 528 229 723 393 600 472 786 ...
##  $ VIVIENDAS  : num  82 365 629 375 445 744 341 505 504 546 ...
##  $ HOGARES    : num  65 116 101 136 129 314 209 275 202 347 ...
##  $ HOGARES_NBI: num  19 25 1 7 16 104 110 32 49 89 ...
##  $ AREA_KM2   : num  1.799 0.0186 0.0444 0.3663 0.0184 ...
##  $ geometry   :sfc_MULTIPOLYGON of length 3554; first list element: List of 1
##   ..$ :List of 1
##   .. ..$ : num [1:409, 1:2] -58.4 -58.4 -58.4 -58.4 -58.4 ...
##   ..- attr(*, "class")= chr [1:3] "XY" "MULTIPOLYGON" "sfg"
##  - attr(*, "sf_column")= chr "geometry"
##  - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA
##   ..- attr(*, "names")= chr [1:8] "RADIO_ID" "BARRIO" "COMUNA" "POBLACION" ...

Como puede advertirse, se trata de tres dataframes de datos espaciales: el primero de ellos contiene datos generales de los polígonos de los barrios de la Ciudad de Buenos Aires; el segundo, de sus hospitales; y el tercero, datos sociodemográficos correspondienteas al último censo para cada uno de los radios censales de la ciudad. Asimismo, puede apreciarse que todos los dataframes tienen un sistama de coordenadas de referencia (CRS) geodésico.

2.Transformación de datos

Antes de poder generar visualizaciones de los datos que estamos analizando debermos realizar algunas transformaciones. En este sentido, uniremos los datos de nuestros dataframes a partir de su ubicación espacial y realizaremos un recorte de las variables y las observaciones que nos interesan a los efectos de lo que queremos analizar.

barrios_caba <- barrios_caba %>%  
                rename(COMUNA=comuna, BARRIO=barrio) %>% 
                mutate(COMUNA=as.factor(COMUNA)) %>% 
                select(!area & !perimetro)
hospitales <- st_join(hospitales, barrios_caba)
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
hospitales_por_tipo_y_comuna <- hospitales %>%
                                st_set_geometry(NULL) %>%
                                group_by(COMUNA, TIPO) %>% 
                                summarise(CANTIDAD=n())
## `summarise()` has grouped output by 'COMUNA'. You can override using the `.groups` argument.
datos_censales_xbarrio <- datos_censales_xradio %>%
                          st_set_geometry(NULL) %>%
                          group_by(BARRIO) %>% 
                          summarise(POBLACION=sum(POBLACION),AREA_KM2=sum(AREA_KM2))
hospitales_por_barrio <- hospitales %>% 
                         st_set_geometry(NULL) %>%
                         group_by(BARRIO) %>% 
                         summarise(CANTIDAD_HOSP=n()) %>% 
                         mutate_all(~replace(., is.na(.), 0))
hospitales_por_area_y_poblacion <- datos_censales_xbarrio %>% 
                                 left_join(hospitales_por_barrio, by="BARRIO") %>% 
                                 mutate_all(~replace(., is.na(.), 0)) %>% 
                                 mutate(HOSPx10KHAB=CANTIDAD_HOSP/POBLACION*10000, HOSPxKM2= CANTIDAD_HOSP/AREA_KM2)
hospitales_por_area_y_poblacion
## # A tibble: 48 x 6
##    BARRIO    POBLACION AREA_KM2 CANTIDAD_HOSP HOSPx10KHAB HOSPxKM2
##    <chr>         <dbl>    <dbl>         <dbl>       <dbl>    <dbl>
##  1 AGRONOMIA     13912     2.12             0      0         0    
##  2 ALMAGRO      131699     4.05             1      0.0759    0.247
##  3 BALVANERA    138926     4.34             1      0.0720    0.230
##  4 BARRACAS      89452     7.96             6      0.671     0.754
##  5 BELGRANO     126267     7.73             1      0.0792    0.129
##  6 BOCA          45113     5.02             2      0.443     0.398
##  7 BOEDO         47306     2.61             0      0         0    
##  8 CABALLITO    176076     6.85             4      0.227     0.584
##  9 CHACARITA     27761     3.12             0      0         0    
## 10 COGHLAN       18604     1.28             1      0.538     0.781
## # … with 38 more rows
hospitales_por_area_y_poblacion_geo <- barrios_caba %>%  
                                       left_join(hospitales_por_area_y_poblacion, by="BARRIO")

3.Visualización de datos

i) Gráfico de Barras

En nuestra primera visualización, crearemos un gráfico de barras que contrasta la cantidad de hospitales existente en cada comuna de la Ciudad de Buenos Aires:

ggplot(data=hospitales_por_tipo_y_comuna, aes(fill=TIPO, y=COMUNA, x=CANTIDAD)) + 
    geom_bar(stat="identity", width = 0.5) +
    theme_minimal() +
    theme(plot.title = element_text(face="bold", size=15)) +
    theme(axis.title.x = element_text(face="bold", vjust=-0.5, colour="darkgray", size=12)) +
    theme(axis.title.y = element_text(face="bold", vjust=-0.5, colour="darkgray", size=12)) + 
    scale_fill_viridis_d()+
    scale_y_discrete(limit = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" ))+
    scale_x_continuous(breaks = seq(0, 14, 2))+
    labs(title = "Hospitales de la ciudad de Buenos Aires", 
    subtitle = "Cantidad de hospitales por tipo y comuna",
    x = "Cantidad de hospitales",
    y = "Comuna",
    caption = "fuente: Buenos Aires Data",
    fill = "Tipo")

Como puede observarse en el gráfico, más de un tercio (13 de 36) de los hospitales de la ciudad se localizan en una sóla Comuna, la 4; mientras que la Comuna 1 no cuenta con ninguno y la mayoría de las comunas cuentan con uno o dos. Otras comunas que concentran más hospitales que el promedio son la Comuna 2, con 3 hospitales y la Comuna 6, con 4. En este sentido, una primera conclusión que podemos sacar de la visualización de los datos es que no existe una cobertura hospitalaria homogénea en la ciudad, sino que, por el contrario, los hospitales se encuentran concentrados en pocos barrios. Si bien esto puede redundar en beneficios operativos para la gestión del sistema público de salud, constituye un abstáculo evidente para el acceso a la atención hospitalaria. Asimismo, hemos visto que existe una ausencia completa de hospitales solamente en una única comuna. Esto podría deberse a que dicha comuna, la 1, es precisamente la que concentra la mayor proporción de usos no residenciales: administración pública, financiero, comercial, etc.

ii) Mapa Coroplético

Como hemos adelantado, para poder realizar una comparación más precisa de la cobertura hospitalaria entre unidades territoriales de diferentes tamaños y densidad poblacional, resulta necesario comparar la cantidad de hospitales no en términos absolutos (cuántos hay por barrio o comuna) sino en términos relavivos en relación a su población y superficie. Para ello, para nuestra segunda visualización, realizamos dos mapas de coropletas que nos permiten visualizar la cantidad de hospitales por km2 y por cada diez mil habitantes

bbox_barrios <- as.numeric(st_bbox(barrios_caba))
mapa_caba <- get_stamenmap(bbox = bbox_barrios, maptype = "toner-lite", zoom=12) 
## Source : http://tile.stamen.com/toner-lite/12/1382/2467.png
## Source : http://tile.stamen.com/toner-lite/12/1383/2467.png
## Source : http://tile.stamen.com/toner-lite/12/1384/2467.png
## Source : http://tile.stamen.com/toner-lite/12/1382/2468.png
## Source : http://tile.stamen.com/toner-lite/12/1383/2468.png
## Source : http://tile.stamen.com/toner-lite/12/1384/2468.png
## Source : http://tile.stamen.com/toner-lite/12/1382/2469.png
## Source : http://tile.stamen.com/toner-lite/12/1383/2469.png
## Source : http://tile.stamen.com/toner-lite/12/1384/2469.png
  • Mapa 1: Hospitales por kilómetro cuadrado
ggmap(mapa_caba)+ 
  geom_sf(data=hospitales_por_area_y_poblacion_geo, aes(fill=HOSPxKM2), inherit.aes = FALSE, alpha=0.75)+
  scale_fill_viridis_c() +
  theme_void() +
    theme(plot.title = element_text(face="bold", size=15)) +
    theme(axis.title.x = element_text(face="bold", vjust=-0.5, colour="darkgray", size=12)) +
    theme(axis.title.y = element_text(face="bold", vjust=-0.5, colour="darkgray", size=12)) + 
    labs(title = "La Cobretura hospitalaria de la ciudad", 
    subtitle = "Hospitales por kilómetro cuadrado en CABA",
    fill = NULL,
    caption = "fuente: Buenos Aires Data")
## Coordinate system already present. Adding new coordinate system, which will replace the existing one.

  • Mapa 2: Hospitales cada 10 mil habitantes
ggmap(mapa_caba)+ 
  geom_sf(data=hospitales_por_area_y_poblacion_geo, aes(fill=HOSPx10KHAB), inherit.aes = FALSE, alpha=0.75)+
  scale_fill_viridis_c() +
  theme_void() +
    theme(plot.title = element_text(face="bold", size=15)) +
    theme(axis.title.x = element_text(face="bold", vjust=-0.5, colour="darkgray", size=12)) +
    theme(axis.title.y = element_text(face="bold", vjust=-0.5, colour="darkgray", size=12)) + 
    labs(title = "La Cobretura hospitalaria de la ciudad", 
    subtitle = "Hospitales cada 10 mil habitantes en CABA",
    fill = NULL,
    caption = "fuente: Buenos Aires Data")
## Coordinate system already present. Adding new coordinate system, which will replace the existing one.

Como puede observarse, ambos mapas resultan casi idénticos y dan una idea más precisa de la cobertura hospitalaria en términos relativos a nivel barrio. Si bien estos mapas siguen evidenciando una fuerte concentración espacial de la cobertura hospitalaria nos muestran mayores matices que el gráfico de barras, tanto por tratarse de una unidad territorial de análisis menor, como por la posibilidad de realizar comparaciones entre ellas en términos relativos en lugar de absolutos. En este sentido, se destaca que si bien Barracas es el barrio con más hospitales (posee 6), Parque Patricios (que tiene 5) tiene una proporción mayor de hospitales por km2 o medidos cada diez mil habitantes. Asimismo mientras Parque Chas, Coghlan y Paternal tienen sólo un hospital y Monte Castro y La Boca, 2, todos estos barrios poseen una mayor proporción de barrios por kilómetro cuadrado y cada diez mil habitantes que barrios como Recoleta y Caballito, que poseen 4 y 3 hospitales respectivamente.