05 | Tarea: Analizando y Visualizando Flujos de Viajes Urbanos

library(tidyverse)
library(sf)
library(osmdata)
library(leaflet)
library(ggmap)
library(lubridate)
library(osrm)

1. Elegir UNA SOLA de las siguientes opciones: 1.a. Un dataset que contenga viajes origen-destino (por ejemplo bicicletas públicas) de la Ciudad con la que están trabajando.

Descargamos el dataset de recorridos de ecobicis de la CABA y de las estaciones:

viajes_2021 <- read.csv("recorridos-realizados-2021.csv")
estaciones_ecobici <- read.csv("nuevas-estaciones-bicicletas-publicas.csv", stringsAsFactors = TRUE)
summary(estaciones_ecobici)
##                                           WKT            id       
##  POINT (-58.3557441485293 -34.6188407590044):  1   Min.   :  2.0  
##  POINT (-58.3562543312869 -34.6287585370652):  1   1st Qu.: 81.0  
##  POINT (-58.3596264980273 -34.6181657788322):  1   Median :158.0  
##  POINT (-58.3612804225292 -34.6118156258636):  1   Mean   :171.1  
##  POINT (-58.3620656908362 -34.6307780548633):  1   3rd Qu.:247.0  
##  POINT (-58.3621265468935 -34.624256405674) :  1   Max.   :409.0  
##  (Other)                                    :223                  
##      codigo                            nombre   
##  Min.   :  0.0   001 - FACULTAD DE DERECHO:  1  
##  1st Qu.: 79.0   002 - Retiro I           :  1  
##  Median :156.0   003 - ADUANA             :  1  
##  Mean   :168.5   004 - Plaza Roma         :  1  
##  3rd Qu.:252.0   005 - Plaza Italia       :  1  
##  Max.   :399.0   006 - Parque Lezama      :  1  
##                  (Other)                  :223  
##                                             ubicacion            tipo    
##  1019 Riglos                                     :  1   AUTOMÃ\201TICA:229  
##  1019 Saavedra                                   :  1                    
##  1052 Avalos                                     :  1                    
##  1078 Gurruchaga                                 :  1                    
##  1185 AV. Udaondo                                :  1                    
##  1226 Ecuador & Mansilla, Lucio Norberto, General:  1                    
##  (Other)                                         :223                    
##                                                horario      anclajes_t   
##  Estación automática: disponibilidad las 24 horas:229   Min.   : 8.00  
##                                                           1st Qu.:16.00  
##                                                           Median :20.00  
##                                                           Mean   :19.67  
##                                                           3rd Qu.:20.00  
##                                                           Max.   :42.00  
## 
summary(viajes_2021)
##        ID           Estado.cerrado       Duración      
##  Min.   : 9646392   Length:1328726     Min.   :      0  
##  1st Qu.:10032866   Class :character   1st Qu.:    649  
##  Median :10411240   Mode  :character   Median :   1030  
##  Mean   :10418020                      Mean   :   1214  
##  3rd Qu.:10803894                      3rd Qu.:   1531  
##  Max.   :11204995                      Max.   :5513940  
##                                                         
##  Id.de.estación.de.inicio Fecha.de.inicio    Nombre.de.estación.de.inicio
##  Min.   :  2.0             Length:1328726     Length:1328726               
##  1st Qu.: 75.0             Class :character   Class :character             
##  Median :162.0             Mode  :character   Mode  :character             
##  Mean   :167.6                                                             
##  3rd Qu.:235.0                                                             
##  Max.   :449.0                                                             
##                                                                            
##  Fecha.de.fin       Id.de.estación.de.fin.de.viaje
##  Length:1328726     Min.   :  2.0                  
##  Class :character   1st Qu.: 76.0                  
##  Mode  :character   Median :164.0                  
##                     Mean   :169.1                  
##                     3rd Qu.:236.0                  
##                     Max.   :449.0                  
##                     NA's   :3                      
##  Nombre.de.estación.de.fin.de.viaje ID.de.ciclista   Tipo.de.ciclista  
##  Length:1328726                      Min.   :    38   Length:1328726    
##  Class :character                    1st Qu.:192883   Class :character  
##  Mode  :character                    Median :570673   Mode  :character  
##                                      Mean   :465228                     
##                                      3rd Qu.:712061                     
##                                      Max.   :772265                     
##                                                                         
##  Modelo.de.bicicleta Origen.de.viaje   
##  Length:1328726      Length:1328726    
##  Class :character    Class :character  
##  Mode  :character    Mode  :character  
##                                        
##                                        
##                                        
## 

Eliminamos alguns columnas que no son necesarias para nuestro análisis:

viajes_2021 <- select(viajes_2021, !Estado.cerrado & !Tipo.de.ciclista & !Modelo.de.bicicleta & !Origen.de.viaje & !Fecha.de.fin & !Fecha.de.inicio)
viajes_2021 <- viajes_2021 %>% mutate_if(is.character,as.factor)
summary(viajes_2021)
##        ID             Duración       Id.de.estación.de.inicio
##  Min.   : 9646392   Min.   :      0   Min.   :  2.0            
##  1st Qu.:10032866   1st Qu.:    649   1st Qu.: 75.0            
##  Median :10411240   Median :   1030   Median :162.0            
##  Mean   :10418020   Mean   :   1214   Mean   :167.6            
##  3rd Qu.:10803894   3rd Qu.:   1531   3rd Qu.:235.0            
##  Max.   :11204995   Max.   :5513940   Max.   :449.0            
##                                                                
##                Nombre.de.estación.de.inicio Id.de.estación.de.fin.de.viaje
##  014 - Pacifico               :  18497       Min.   :  2.0                  
##  029 - Parque Centenario      :  17789       1st Qu.: 76.0                  
##  160 - Godoy Cruz y Libertador:  17527       Median :164.0                  
##  255 - BARRANCAS DE BELGRANO  :  14996       Mean   :169.1                  
##  292 - PLAZA BOLIVIA          :  14760       3rd Qu.:236.0                  
##  005 - Plaza Italia           :  14401       Max.   :449.0                  
##  (Other)                      :1230756       NA's   :3                      
##             Nombre.de.estación.de.fin.de.viaje ID.de.ciclista  
##  160 - Godoy Cruz y Libertador:  17982          Min.   :    38  
##  014 - Pacifico               :  17417          1st Qu.:192883  
##  029 - Parque Centenario      :  17008          Median :570673  
##  255 - BARRANCAS DE BELGRANO  :  15305          Mean   :465228  
##  292 - PLAZA BOLIVIA          :  15122          3rd Qu.:712061  
##  096 - Carlos Gardel          :  13870          Max.   :772265  
##  (Other)                      :1232022

Aplicamos la función rename para emprolijar los encabezados de nuestras columnas:

viajes_2021 <- viajes_2021 %>%
  rename(ID_Inicio=Id.de.estación.de.inicio,
         Nombre_Inicio=Nombre.de.estación.de.inicio,
         ID_Fin=Id.de.estación.de.fin.de.viaje,
         Nombre_Fin=Nombre.de.estación.de.fin.de.viaje)

2. Según la opción elegida en el punto 1, deberán:

2.a. Viajes origen-destino: Calcular los 10 recorridos más realizados, describir los resultados obtenidos y hacer un mapa con los ruteos.

Primero, debemos agrupar por estación de inicio y de finalización de viajes para obtener una cantidad total de cada recorrido realizado:

viajes_unit <- viajes_2021 %>% 
    group_by(ID_Inicio, Nombre_Inicio, ID_Fin, Nombre_Fin) %>% 
    summarise(cant_viajes = n())
## `summarise()` has grouped output by 'ID_Inicio', 'Nombre_Inicio', 'ID_Fin'. You can override using the `.groups` argument.

A continuación, realizamos el ranking de los 10 viajes más realizados según nuestro dataset y realizamos un gráfico para poder visualizar mejor los resultados obtenidos:

viajes_unit %>%
  arrange(desc(cant_viajes)) %>%
  head()
## # A tibble: 6 x 5
## # Groups:   ID_Inicio, Nombre_Inicio, ID_Fin [6]
##   ID_Inicio Nombre_Inicio             ID_Fin Nombre_Fin              cant_viajes
##       <int> <fct>                      <dbl> <fct>                         <int>
## 1       152 152 - JULIETA LANTERI        152 152 - JULIETA LANTERI          2748
## 2       268 399 - GARCIA DEL RIO         268 399 - GARCIA DEL RIO           2380
## 3       222 160 - Godoy Cruz y Liber~    222 160 - Godoy Cruz y Lib~        2133
## 4       277 292 - PLAZA BOLIVIA          277 292 - PLAZA BOLIVIA            2125
## 5        29 029 - Parque Centenario       29 029 - Parque Centenario        2046
## 6       210 335 - General Urquiza        210 335 - General Urquiza          1515
top_10 <- viajes_unit %>%
          filter(ID_Inicio != ID_Fin) %>% 
          arrange(desc(cant_viajes)) %>%
          head(10)
ggplot() + 
    geom_tile(data = top_10, 
              aes(x = as.factor(ID_Inicio),
                  y = as.factor(ID_Fin),
                  fill = cant_viajes)) +
    scale_fill_distiller(palette = "RdYlGn") +
    labs(title="Matriz Origen-Destino",
         subtitle="Top 10 Recorridos en sistema Ecobici - Ciudad Autónoma de buenos Aires",
         x="Estacion Origen",
         y="Estación Destino",
         fill="Viajes")

Podemos observar que los dos recorridos más realizados coinciden. El recorrido más repetido es el de la estación de Galicia hasta la estación de San José de Flores y el recorrido a la inversa ocupa el segundo lugar en el ranking. Podemos también identificar otros dos recorridos cuya frecuencia aproximada se repite en ambos sentidos del recorrido. Los mismo son entre la estación Plaza República del Ecuador (ID 239) y la estación Pacífico (ID 14), y entre la estación Plaza Bolivia (ID 277) y la estración Barrancas de Belgrano (ID 289). En estas combinaciones de estaciones, la cantidad de viajes en un sentido es similar a la cantidad de viajes en el sentido contrario. Esto no ocurre con recorridos que como de la Estación Barrio 31 (ID 448) y la estación Retiro II (ID 130): en este caso, la estación Barrio 31 es generadora de viajes a la estación Retiro II, pero no recibe viajes desde ese inicio.

A continuación, vamos a mapear el top 10 de recorridos. PAra eso, debemos trabajar un poco con nuestros datasets:

estaciones_ecobici_geo = st_as_sf(estaciones_ecobici, wkt = "WKT")
estaciones_ecobici_geo <- estaciones_ecobici_geo %>%
  rename(geometry=WKT)

Aplicamos el siguiente código para poder separar cada el valor de x e y de la columna de coordenadas. Es necesario realizar esto para poder luego unir este dataset con la ubicación de las estaciones, al dataset de los recorridos:

estaciones_ecobici_geo <- estaciones_ecobici_geo %>%
mutate(lat = unlist(map(estaciones_ecobici_geo$geometry,1)),
long = unlist(map(estaciones_ecobici_geo$geometry,2)))

Left Join de Origen

top_10 <- left_join(top_10, estaciones_ecobici_geo, by=c("Nombre_Inicio"="nombre"))

Left Join de Destino

top_10 <- left_join(top_10, estaciones_ecobici_geo, by=c("Nombre_Fin"="nombre"))
top_10 <- top_10 %>%
  rename(lat_inic=lat.x,
         long_inic=long.x,
         lat_fin=lat.y,
         long_fin=long.y)
top_10
## # A tibble: 10 x 23
## # Groups:   ID_Inicio, Nombre_Inicio, ID_Fin [10]
##    ID_Inicio Nombre_Inicio      ID_Fin Nombre_Fin     cant_viajes  id.x codigo.x
##        <int> <fct>               <dbl> <fct>                <int> <int>    <int>
##  1       335 206 - Galicia         449 352 - San Jos~        1266   303      206
##  2       449 352 - San Jose de~    335 206 - Galicia         1190   405      352
##  3        14 014 - Pacifico        239 391 - Plaza R~         944    13       14
##  4       239 391 - Plaza Repú~     14 014 - Pacifico         935   210      391
##  5       277 292 - PLAZA BOLIV~    289 255 - BARRANC~         898   246      292
##  6       289 255 - BARRANCAS D~    277 292 - PLAZA B~         879   258      255
##  7        14 014 - Pacifico        222 160 - Godoy C~         840    13       14
##  8         5 005 - Plaza Italia    210 335 - General~         817     5        5
##  9         5 005 - Plaza Italia    222 160 - Godoy C~         776     5        5
## 10       448 393 - Barrio 31       130 130 - RETIRO ~         736   403      393
## # ... with 16 more variables: ubicacion.x <fct>, tipo.x <fct>, horario.x <fct>,
## #   anclajes_t.x <int>, geometry.x <POINT>, lat_inic <dbl>, long_inic <dbl>,
## #   id.y <int>, codigo.y <int>, ubicacion.y <fct>, tipo.y <fct>,
## #   horario.y <fct>, anclajes_t.y <int>, geometry.y <POINT>, lat_fin <dbl>,
## #   long_fin <dbl>
viaje1 <- top_10 %>%
          arrange(desc(cant_viajes)) %>%
          head(1)
ruteo_viaje1 <- osrmRoute(src = c(viaje1$Nombre_Inicio, viaje1$lat_inic, viaje1$long_inic), 
                          dst = c(viaje1$Nombre_Fin, viaje1$lat_fin, viaje1$long_fin), 
                          returnclass = "sf", 
                          overview = "full",
                          osrm.profile = "bike")
ruteo_viaje1
## Simple feature collection with 1 feature and 4 fields
## Geometry type: LINESTRING
## Dimension:     XY
## Bounding box:  xmin: -58.47102 ymin: -34.62907 xmax: -58.46272 ymax: -34.61575
## Geodetic CRS:  WGS 84
##         src dst duration distance                       geometry
## 153_218 153 218     8.47   1.7999 LINESTRING (-58.47102 -34.6...

Cargamos el mapa base:

bbox_CABA <- make_bbox(estaciones_ecobici_geo$lat, estaciones_ecobici_geo$long)
mapa_CABA <- get_stamenmap(bbox_CABA,
                             zoom = 12)
## Source : http://tile.stamen.com/terrain/12/1382/2467.png
## Source : http://tile.stamen.com/terrain/12/1383/2467.png
## Source : http://tile.stamen.com/terrain/12/1384/2467.png
## Source : http://tile.stamen.com/terrain/12/1382/2468.png
## Source : http://tile.stamen.com/terrain/12/1383/2468.png
## Source : http://tile.stamen.com/terrain/12/1384/2468.png
ggmap(mapa_CABA)

Mapeamos en leaflet el viaje 1:

leaflet(ruteo_viaje1) %>% 
    addTiles() %>% 
    addPolylines(color = "red")

Podemos observar en el mapa que el recorrido del viaje 1 (es decir, el viaje más frecuente en nuestro top 10) coincide con la información que obtuvimos en el geom_tile: es el recorrido entre la estación de la calle Galicia y la estación San José de Flores.

Varios ruteos a la vez

A continuación vamos a mapear los 10 viajes con mayor frecuencia.

ruteo_ecobici <- function(Nombre_inicio, lat_inic, long_inic,
                        Nombre_Fin, lat_fin, long_fin) {
  ruta <- osrmRoute(src = c(Nombre_inicio, lat_inic, long_inic),
                    dst = c(Nombre_Fin, lat_fin, long_fin), 
                    returnclass = "sf",
                    overview = "full",
                    osrm.profile = "bike")
  
  cbind(Nombre_inicio, Nombre_Fin, ruta)}
ruteo_top10 <- list(top_10$Nombre_Inicio, top_10$lat_inic, top_10$long_inic,
                   top_10$Nombre_Fin, top_10$lat_fin, top_10$long_fin)
ruteo_top10 <- pmap(ruteo_top10, ruteo_ecobici) %>% 
  reduce(rbind)
summary(ruteo_top10)
##                      Nombre_inicio                         Nombre_Fin
##  005 - Plaza Italia         :2     160 - Godoy Cruz y Libertador:2   
##  014 - Pacifico             :2     014 - Pacifico               :1   
##  206 - Galicia              :1     130 - RETIRO II              :1   
##  255 - BARRANCAS DE BELGRANO:1     206 - Galicia                :1   
##  292 - PLAZA BOLIVIA        :1     255 - BARRANCAS DE BELGRANO  :1   
##  352 - San Jose de Flores   :1     292 - PLAZA BOLIVIA          :1   
##  (Other)                    :2     (Other)                      :3   
##       src             dst           duration        distance     
##  Min.   :  5.0   Min.   : 13.0   Min.   :4.153   Min.   :0.9627  
##  1st Qu.: 12.0   1st Qu.:121.0   1st Qu.:5.941   1st Qu.:1.2523  
##  Median :164.5   Median :166.5   Median :7.075   Median :1.5701  
##  Mean   :123.2   Mean   :154.6   Mean   :6.814   Mean   :1.4735  
##  3rd Qu.:210.5   3rd Qu.:208.0   3rd Qu.:8.081   3rd Qu.:1.7022  
##  Max.   :229.0   Max.   :231.0   Max.   :8.470   Max.   :1.7999  
##                                                                  
##           geometry 
##  LINESTRING   :10  
##  epsg:4326    : 0  
##  +proj=long...: 0  
##                    
##                    
##                    
## 
ggmap(mapa_CABA)+
  geom_sf(data=ruteo_top10, color="red", size=1.5, inherit.aes = FALSE)+
  labs(title="Top 10 Recorridos Ecobici",
       caption="Fuente: Buenos Aires Open Data")+
  scale_color_viridis_c(direction=-1)+
  theme_void()
## Coordinate system already present. Adding new coordinate system, which will replace the existing one.

En el mapa podemos observar que hay menos de 10 recorridos marcados. Esto se debe a que, como dijimos en el punto anterior, de los 10 recorridos hay 6 recorridos que se repiten pero en sentido contrario, con lo cual las líneas reflejan en algunos casos ambos sentidos del recorrido.

ruteo_top10 <- ruteo_top10 %>%
  mutate(RUTA = paste("Desde", Nombre_inicio,"hasta", Nombre_Fin))

Por último, vamos a mapear los recorridos, incorporando la variable de distancia de los mismos.

paleta <- c(low="gold", high= "deeppink4")

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

leaflet(ruteo_top10) %>%
  addTiles() %>%
  addProviderTiles(providers$CartoDB) %>%
  addPolylines(color = ~colorNumeric(paleta, ruteo_top10$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_top10$distance), values = ~distance,
            title = "Distancia",
            labFormat = labelFormat(suffix = "km"),
            opacity = 0.75)

Como podemos observar en el mapa, los 10 recorridos más frecuentes no superan una distancia de 1,7km. Es decir que en todos los casos, y como era esperable al tratarse de un medio de transporte de tracción a sangre, son recorridos de “última milla”.

La mayoría de los recorridos top 10 están concentrados en el corredor norte y más específicamente en el barrio de Palermo. Esto podría sugerir un perfil específico tanto del usuario de la ecobici como del tipo de recorrido que se demanda. Si bien es necesario obtener más información para poder concluir definitivamente, podríamos aasociar esto a que parte de esos viajes en ecobici estén ligados al uso de los parques (por motivos de esparcimiento por ejemplo) ubicados en esta zona de la ciudad. Asimismo, dos de los recorridos tienen como nodo de inicio o fin Plaza Italia, lo cual puede suponer que se está usando la ecobici como un medio de transbordo para conectar distintos medios transporte.