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.