En el presente trabajo, vamos a calcular el recorrido, tiempo y distancia entre el centroide y las comisarias para los barrios de Palermo y Belgrano.

Primero, activamos las librerias necesarias:

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ ggplot2 3.3.3     ✓ purrr   0.3.4
## ✓ tibble  3.1.1     ✓ 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.
library(leaflet)
library(osrm)
## Data: (c) OpenStreetMap contributors, ODbL 1.0 - http://www.openstreetmap.org/copyright
## Routing: OSRM - http://project-osrm.org/

Abrimos las bases de datos:

comisarias <- read.csv("comisarias-policia-de-la-ciudad.csv", stringsAsFactors = TRUE) 
barrios <- st_read("http://cdn.buenosaires.gob.ar/datosabiertos/datasets/barrios/barrios.geojson")
## Reading layer `barrios_badata' from data source `http://cdn.buenosaires.gob.ar/datosabiertos/datasets/barrios/barrios.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

Veamos qué tenemos:

head(comisarias)
##        long       lat id                nombre      calle altura calle2
## 1 -58.37324 -34.60191  1 Comisaria Vecinal 1-D    Lavalle    451       
## 2 -58.42493 -34.62864 37 Comisaria Vecinal 5-B      Muñiz   1250       
## 3 -58.43950 -34.60898 39 Comisaria Vecinal 6-A Diaz Velez   5152       
## 4 -58.44809 -34.62678  8 Comisaria Vecinal 7-B      Valle   1454       
## 5 -58.45322 -34.62038 38   Comisaria Comunal 6 Avellaneda   1548       
## 6 -58.38018 -34.59464 10   Comisaria Comunal 1   Suipacha   1156       
##             direccion            telefonos
## 1         LAVALLE 451       4322-8033/8221
## 2          MUÑIZ 1250 4922-1229 /4922-3333
## 3 DIAZ VELEZ AV. 5152       4982-4509/4520
## 4          VALLE 1454       4432-3334/3922
## 5 AVELLANEDA AV. 1548       4632-9051/9129
## 6       SUIPACHA 1156  4393-0076/3333/7058
##                               observaciones observaciones_2      barrio comuna
## 1                                                        NA SAN NICOLAS      1
## 2                                                        NA       BOEDO      5
## 3                                                        NA   CABALLITO      6
## 4 Ubicada en comuna 6, dependencia comuna 7              NA   CABALLITO      6
## 5                                                        NA   CABALLITO      6
## 6                                                        NA      RETIRO      1
##   codigo_postal codigo_postal_argentino
## 1          1047                C1047AAI
## 2          1255                C1255ACD
## 3          1405                C1405DCT
## 4          1406                C1406GTH
## 5          1406                C1406FYN
## 6          1008                C1008AAX

Comisarias es una base de datos que tiene longitud y latitud de cada comisaria, el nombre de la comisaria, el barrio en el que se encuentra y demas datos.

head(barrios)
## Simple feature collection with 6 features and 4 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: -58.50617 ymin: -34.63064 xmax: -58.41192 ymax: -34.57829
## Geodetic CRS:  WGS 84
##             barrio comuna perimetro    area                       geometry
## 1        CHACARITA     15  7724.853 3115707 POLYGON ((-58.45282 -34.595...
## 2         PATERNAL     15  7087.513 2229829 POLYGON ((-58.46558 -34.596...
## 3     VILLA CRESPO     15  8131.857 3615978 POLYGON ((-58.42375 -34.597...
## 4 VILLA DEL PARQUE     11  7705.390 3399596 POLYGON ((-58.49461 -34.614...
## 5          ALMAGRO      5  8537.901 4050752 POLYGON ((-58.41287 -34.614...
## 6        CABALLITO      6 10990.964 6851029 POLYGON ((-58.43061 -34.607...

‘Barrios’ es una base de datos que contiene el perimetro, area y geometria de cada barrio de CABA. Ahora, calculemos el centroide de los Barrios a analizar y transformemos la geometria en coordenadas X (longitud) e Y (latitud).

barrios_centroides <- barrios %>%
  st_centroid() %>%
  filter(barrio=="PALERMO" | barrio=="BELGRANO")
## Warning in st_centroid.sf(.): st_centroid assumes attributes are constant over
## geometries of x
## Warning in st_centroid.sfc(st_geometry(x), of_largest_polygon =
## of_largest_polygon): st_centroid does not give correct centroids for longitude/
## latitude data
barrios_centroides <- cbind(barrios_centroides, st_coordinates(barrios_centroides)) %>%
                      st_set_geometry(NULL) %>% 
                      rename(LON_ORIGEN=X,
                             LAT_ORIGEN=Y)

Generemos el primer mapa donde se muestre la ubicacion de las comisarias por todos los barrios de CABA:

comisarias %>% 
  group_by(barrio) %>% 
  summarise(cantidad=n()) %>%
  mutate(barrio=toupper(barrio)) %>% 
  left_join(barrios, by="barrio") %>%
  ungroup() %>% 
ggplot()+
  geom_sf(data=barrios, fill="gray90", color="white")+
  geom_sf(aes(fill=cantidad, geometry = geometry), color="white")+
  geom_point(data=barrios_centroides, aes(x=LON_ORIGEN, y=LAT_ORIGEN), shape=4, stroke=2, size=2)+
  geom_point(data=comisarias, aes(x=long, y=lat), size=1.5)+
  scale_fill_gradient(low="gold", high= "deeppink4")+
  scale_color_manual(values = c("turquoise4", "magenta4"))+
  labs(title = "Comisarias por barrio",
         fill="",
         color="",
          x="",
          y="",
         caption= "Fuente: Buenos Aires Data")+
  theme(panel.background = element_rect(fill = "gray100", colour = "gray100", size = 2, linetype = "solid"),
        panel.grid.major = element_line(size = 0.5, linetype = "dashed", colour = "gray80"),
        title=element_text(size=10, face = "bold"), plot.title = element_text(hjust = 0.5),
        legend.key.size = unit(0.6, "cm"), legend.key.width = unit(0.5,"cm"),
        legend.text=element_text(size=7),
        plot.caption=element_text(face = "italic", colour = "gray35",size=6),
        axis.text = element_blank(), axis.ticks = element_blank())

Podemos ver como se distribuyen los hospitales de la Ciudad y donde se localizan los 2 centroides a analizar (los puntos X dentro de Palermo y Belgrano). Para hacer el ruteo, necesitaremos crear una función con osrmRoute() que haga los cálculos entre nuestros puntos de origen (centroides de los 2 barrios) y los de destino (comisarias).

##Generemos la función de ruteo

ruteo_comisarias <- function(o_nombre, o_x, o_y, d_nombre, d_x, d_y) {
  ruta <- osrmRoute(src = c(o_nombre, o_x, o_y),
                    dst = c(d_nombre, d_x, d_y), 
                    returnclass = "sf",
                    overview = "full",
                    )
  
  cbind(ORIGEN = o_nombre, DESTINO = d_nombre, ruta)
}

Ahora, debemos gnerar un dataframe para cada barrio que contenga las variables NOMBRE_ORIGEN, LON_ORIGEN, LAT_ORIGEN, NOMBRE_DESTINO, LON_DESTINO y LAT_DESTINO.

###PALERMO

c_palermo <- comisarias %>%
  mutate(NOMBRE_ORIGEN="PALERMO") %>%
  left_join(barrios_centroides, by=c("NOMBRE_ORIGEN"="barrio")) %>%
  rename(NOMBRE_DESTINO=nombre,
         LON_DESTINO=long,
         LAT_DESTINO=lat) %>%
  select(NOMBRE_ORIGEN, LON_ORIGEN, LAT_ORIGEN, NOMBRE_DESTINO, LON_DESTINO, LAT_DESTINO)

head(c_palermo)
##   NOMBRE_ORIGEN LON_ORIGEN LAT_ORIGEN        NOMBRE_DESTINO LON_DESTINO
## 1       PALERMO  -58.42234  -34.57386 Comisaria Vecinal 1-D   -58.37324
## 2       PALERMO  -58.42234  -34.57386 Comisaria Vecinal 5-B   -58.42493
## 3       PALERMO  -58.42234  -34.57386 Comisaria Vecinal 6-A   -58.43950
## 4       PALERMO  -58.42234  -34.57386 Comisaria Vecinal 7-B   -58.44809
## 5       PALERMO  -58.42234  -34.57386   Comisaria Comunal 6   -58.45322
## 6       PALERMO  -58.42234  -34.57386   Comisaria Comunal 1   -58.38018
##   LAT_DESTINO
## 1   -34.60191
## 2   -34.62864
## 3   -34.60898
## 4   -34.62678
## 5   -34.62038
## 6   -34.59464
dim(c_palermo)
## [1] 49  6

ACÁ HAY UN PROBLEMA, ESTÁ GENERANDO 49 VIAJES CUANDO DEBERÍA GENERAR SOLO 3, PUES HAY 3 COMISARIAS EN PALERMO. Hagamos el ruteo:

ruteo_palermo <- list(c_palermo$NOMBRE_ORIGEN, c_palermo$LON_ORIGEN,c_palermo$LAT_ORIGEN,
                   c_palermo$NOMBRE_DESTINO, c_palermo$LON_DESTINO,c_palermo$LAT_DESTINO)

ruteo_P <- pmap(ruteo_palermo, ruteo_comisarias) %>% 
  reduce(rbind)

Veamos los resultados:

summary(ruteo_P)
##     ORIGEN                          DESTINO       src                 dst    
##  Length:49          Comisaria Comunal 1 : 1   Length:49          Min.   : 1  
##  Class :character   Comisaria Comunal 10: 1   Class :character   1st Qu.:13  
##  Mode  :character   Comisaria Comunal 11: 1   Mode  :character   Median :25  
##                     Comisaria Comunal 12: 1                      Mean   :25  
##                     Comisaria Comunal 13: 1                      3rd Qu.:37  
##                     Comisaria Comunal 14: 1                      Max.   :49  
##                     (Other)             :43                                  
##     duration         distance               geometry 
##  Min.   : 3.547   Min.   : 1.990   LINESTRING   :49  
##  1st Qu.: 9.352   1st Qu.: 5.719   epsg:4326    : 0  
##  Median :13.568   Median : 8.018   +proj=long...: 0  
##  Mean   :12.867   Mean   : 8.006                     
##  3rd Qu.:15.413   3rd Qu.: 9.485                     
##  Max.   :24.025   Max.   :16.257                     
## 

Se agregaron 2 nuevos campos llamados duration y distance. Notar que: -la duracion promedio de un viaje caminando desde el centroide de Palermo hasta una comisaria es de 12 minutos -la distancia promedio de un viaje caminando desde el centroide de Palermo hasta una comisaria es de 800 metros. -la comisaria mas cercana está a 190 metros y a 3 minutos y medio. -la comisaria mas alejada está a 1,6 kilometros y a 24 minutos.

¿Cuál es la comisaria más cercano al centro de Palermo?

filter(ruteo_P, distance == min(distance))$DESTINO
## [1] Comisaria Vecinal 14-B
## 49 Levels: Comisaria Comunal 1 Comisaria Comunal 10 ... Comisaria Vecinal 9-B

Veamoslo en un mapa:

ruteo_P <- ruteo_P %>%
  mutate(RUTA=paste("Desde", ORIGEN, "Hasta", DESTINO))
paleta <- c(low="gold", high= "deeppink4")

labels <- sprintf(
  "<strong>%s</strong><br/>%g km <br/>%g min",
  ruteo_P$RUTA, round(ruteo_P$distance, 2), round(ruteo_P$duration, 0)
) %>% lapply(htmltools::HTML)

leaflet(ruteo_P) %>%
  addTiles() %>%
  addProviderTiles(providers$CartoDB) %>%
  addPolylines(color = ~colorNumeric(paleta, ruteo_P$distance)(distance),
               weight = 6,
               label = labels,
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "2px 5px"),
      textsize = "10px",
      direction = "top"),
              highlight = highlightOptions(weight = 8,
                                           bringToFront = TRUE)) %>% 
  addLegend("bottomright", pal = colorNumeric(paleta, ruteo_P$distance), values = ~distance,
            title = "Distancia",
            labFormat = labelFormat(suffix = "km"),
            opacity = 0.75)

En el mapa no puede verse pues está el problema de que genera 49 viajes en lugar de 3. Si ese problema estuviera resuelto, se visualizarian los 3 viajes.

##BELGRANO:

c_belgrano <- comisarias %>%
  mutate(NOMBRE_ORIGEN="BELGRANO") %>%
  left_join(barrios_centroides, by=c("NOMBRE_ORIGEN"="barrio")) %>%
  rename(NOMBRE_DESTINO=nombre,
         LON_DESTINO=long,
         LAT_DESTINO=lat) %>%
  select(NOMBRE_ORIGEN, LON_ORIGEN, LAT_ORIGEN, NOMBRE_DESTINO, LON_DESTINO, LAT_DESTINO)

head(c_belgrano)
##   NOMBRE_ORIGEN LON_ORIGEN LAT_ORIGEN        NOMBRE_DESTINO LON_DESTINO
## 1      BELGRANO  -58.45024  -34.55476 Comisaria Vecinal 1-D   -58.37324
## 2      BELGRANO  -58.45024  -34.55476 Comisaria Vecinal 5-B   -58.42493
## 3      BELGRANO  -58.45024  -34.55476 Comisaria Vecinal 6-A   -58.43950
## 4      BELGRANO  -58.45024  -34.55476 Comisaria Vecinal 7-B   -58.44809
## 5      BELGRANO  -58.45024  -34.55476   Comisaria Comunal 6   -58.45322
## 6      BELGRANO  -58.45024  -34.55476   Comisaria Comunal 1   -58.38018
##   LAT_DESTINO
## 1   -34.60191
## 2   -34.62864
## 3   -34.60898
## 4   -34.62678
## 5   -34.62038
## 6   -34.59464
dim(c_belgrano)
## [1] 49  6

Nuevamente, el mismo problema. Genera 49 viajes cuando deberia generar 2, pues hay 2 comisarias en Belgrano.

Hacemos el ruteo:

ruteo_belgrano <- list(c_belgrano$NOMBRE_ORIGEN, c_belgrano$LON_ORIGEN,c_belgrano$LAT_ORIGEN,
                   c_belgrano$NOMBRE_DESTINO, c_belgrano$LON_DESTINO,c_belgrano$LAT_DESTINO)

ruteo_B <- pmap(ruteo_belgrano, ruteo_comisarias) %>% 
  reduce(rbind)

Veamos los resultados:

summary(ruteo_B)
##     ORIGEN                          DESTINO       src                 dst    
##  Length:49          Comisaria Comunal 1 : 1   Length:49          Min.   : 1  
##  Class :character   Comisaria Comunal 10: 1   Class :character   1st Qu.:13  
##  Mode  :character   Comisaria Comunal 11: 1   Mode  :character   Median :25  
##                     Comisaria Comunal 12: 1                      Mean   :25  
##                     Comisaria Comunal 13: 1                      3rd Qu.:37  
##                     Comisaria Comunal 14: 1                      Max.   :49  
##                     (Other)             :43                                  
##     duration         distance               geometry 
##  Min.   : 2.292   Min.   : 1.062   LINESTRING   :49  
##  1st Qu.:11.465   1st Qu.: 6.783   epsg:4326    : 0  
##  Median :15.480   Median : 9.928   +proj=long...: 0  
##  Mean   :15.270   Mean   :10.144                     
##  3rd Qu.:18.717   3rd Qu.:13.255                     
##  Max.   :28.185   Max.   :22.266                     
## 

Se agregaron 2 nuevos campos llamados duration y distance. Notar que: -la duracion promedio de un viaje desde el centroide de Belgrano hasta una comisaria es de 15 minutos (esto creo esta mal por el hecho de que genera mas de 2 viajes, xq hay 2 comisarias en Belgrano). -la distancia promedio de un viaje desde el centroide de Belgrano hasta una comisaria es de 10 kmmetros (esto creo esta mal por el hecho de que genera mas de 2 viajes, xq hay 2 comisarias en Belgrano). -la comisaria mas cercana está a 1 kmy a 2 minutos.

¿Cuál es la comisaria más cercano al centro de Belgrano?

filter(ruteo_B, distance == min(distance))$DESTINO
## [1] Comisaria Comunal 13
## 49 Levels: Comisaria Comunal 1 Comisaria Comunal 10 ... Comisaria Vecinal 9-B

Veamoslo en un mapa:

ruteo_B <- ruteo_B %>%
  mutate(RUTA=paste("Desde", ORIGEN, "Hasta", DESTINO))
paleta <- c(low="gold", high= "deeppink4")

labels <- sprintf(
  "<strong>%s</strong><br/>%g km <br/>%g min",
  ruteo_B$RUTA, round(ruteo_B$distance, 2), round(ruteo_B$duration, 0)
) %>% lapply(htmltools::HTML)

leaflet(ruteo_B) %>%
  addTiles() %>%
  addProviderTiles(providers$CartoDB) %>%
  addPolylines(color = ~colorNumeric(paleta, ruteo_B$distance)(distance),
               weight = 6,
               label = labels,
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "2px 5px"),
      textsize = "10px",
      direction = "top"),
              highlight = highlightOptions(weight = 8,
                                           bringToFront = TRUE)) %>% 
  addLegend("bottomright", pal = colorNumeric(paleta, ruteo_B$distance), values = ~distance,
            title = "Distancia",
            labFormat = labelFormat(suffix = "km"),
            opacity = 0.75)

En el mapa no puede verse pues está el problema de que genera 49 viajes en lugar de 2. Si ese problema estuviera resuelto, se visualizarian los 2 viajes.