library(ggmap)
## Warning: package 'ggmap' was built under R version 3.6.1
## Loading required package: ggplot2
## Registered S3 methods overwritten by 'ggplot2':
## method from
## [.quosures rlang
## c.quosures rlang
## print.quosures rlang
## 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(tidyverse)
## Registered S3 method overwritten by 'rvest':
## method from
## read_xml.response xml2
## -- Attaching packages -------------------------------------------------- tidyverse 1.2.1 --
## v tibble 2.1.1 v purrr 0.3.2
## v tidyr 0.8.3 v dplyr 0.8.0.1
## v readr 1.3.1 v stringr 1.4.0
## v tibble 2.1.1 v forcats 0.4.0
## -- Conflicts ----------------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(sf)
## Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3
library(osmdata)
## Warning: package 'osmdata' was built under R version 3.6.1
## Data (c) OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright
library(leaflet)
## Warning: package 'leaflet' was built under R version 3.6.1
Vamos a analizar los viajes origen-destino del sistema de EcoBici 2018
bici <- read.csv('C:/MEU (DiTella)/2019 - A2/2 Trimestre/MU115 - Ciencia de datos 2/Datos2/BA/bici/recorridos-realizados-2018.csv', encoding = "UTF-8")
Exploramos el dataset
dim(bici)
## [1] 2619968 9
names(bici)
## [1] "bici_id_usuario" "bici_Fecha_hora_retiro"
## [3] "bici_tiempo_uso" "bici_nombre_estacion_origen"
## [5] "bici_estacion_origen" "bici_nombre_estacion_destino"
## [7] "bici_estacion_destino" "bici_sexo"
## [9] "bici_edad"
summary(bici)
head(bici)
## bici_id_usuario bici_Fecha_hora_retiro bici_tiempo_uso
## 1 5453 2018-01-01 00:08:05 0 days 00:19:53.000000000
## 2 673 2018-01-01 00:18:05 0 days 00:26:19.000000000
## 3 179119 2018-01-01 00:20:14 0 days 00:27:39.000000000
## 4 400147 2018-01-01 00:20:22 0 days 00:48:51.000000000
## 5 400156 2018-01-01 00:20:31 0 days 00:49:27.000000000
## 6 476733 2018-01-01 00:21:01 0 days 00:36:10.000000000
## bici_nombre_estacion_origen bici_estacion_origen
## 1 Uruguay 45
## 2 Posadas 189
## 3 Hospital Rivadavia 50
## 4 Macacha Güemes 111
## 5 Macacha Güemes 111
## 6 Yatay 121
## bici_nombre_estacion_destino bici_estacion_destino bici_sexo bici_edad
## 1 Virrey Cevallos 183 M 45
## 2 Guardia Vieja 110 M 61
## 3 Padilla 31 F 52
## 4 Acuña de Figueroa 54 M 27
## 5 Acuña de Figueroa 54 F 27
## 6 Billinghurst y Valentin Gomez 143 F 31
Tenemos la cantidad de viajes, pero queremos conocer la cantidad de estaciones, por lo que creamos un contador
conteo.est <- bici %>%
group_by(bici_nombre_estacion_origen) %>%
summarise(cantidad = n())
dim(conteo.est)
## [1] 199 2
Ya tenemos los recorridos y cantidad de estaciones, ahora vamos a descargar el dataset de Estaciones para ver la ubicacion, que es el dato que nos esta faltando.
estaciones <- read.csv('C:/MEU (DiTella)/2019 - A2/2 Trimestre/MU115 - Ciencia de datos 2/Datos2/BA/bici/estaciones-de-bicicletas-publicas.csv', encoding = "UTF-8")
Exploramos
names(estaciones)
## [1] "long" "lat" "nombre" "domicilio" "imagen"
## [6] "automat" "observ" "nro_est" "horario" "dire_norm"
dim(estaciones)
## [1] 199 10
Ambos datasets nos indican que hay 199 estaciones. Vamos a visualizarlas
Definimos el BoundingBox
library(ggmap)
bbox <- make_bbox(estaciones$X, estaciones$Y)
## Warning in min(x, na.rm = na.rm): ningún argumento finito para min;
## retornando Inf
## Warning in max(x, na.rm = na.rm): ningun argumento finito para max;
## retornando -Inf
## Warning in min(x, na.rm = na.rm): ningún argumento finito para min;
## retornando Inf
## Warning in max(x, na.rm = na.rm): ningun argumento finito para max;
## retornando -Inf
bbox
## left bottom right top
## -Inf -Inf Inf Inf
bbox <- c(min(estaciones$lon),
min(estaciones$lat),
max(estaciones$lon),
max(estaciones$lat))
mapa_base <- get_stamenmap(bbox, color = "bw", zoom = 13)
## Source : http://tile.stamen.com/terrain/13/2765/4935.png
## Source : http://tile.stamen.com/terrain/13/2766/4935.png
## Source : http://tile.stamen.com/terrain/13/2767/4935.png
## Source : http://tile.stamen.com/terrain/13/2768/4935.png
## Source : http://tile.stamen.com/terrain/13/2765/4936.png
## Source : http://tile.stamen.com/terrain/13/2766/4936.png
## Source : http://tile.stamen.com/terrain/13/2767/4936.png
## Source : http://tile.stamen.com/terrain/13/2768/4936.png
## Source : http://tile.stamen.com/terrain/13/2765/4937.png
## Source : http://tile.stamen.com/terrain/13/2766/4937.png
## Source : http://tile.stamen.com/terrain/13/2767/4937.png
## Source : http://tile.stamen.com/terrain/13/2768/4937.png
ggmap(mapa_base) +
geom_point(data = estaciones,
aes(x = long, y = lat),
alpha = .8,
color = "orange")
Si queremos saber cuales son los trayectos mas populares, podemos armar un contador que contabilize pares de estaciones
conteo <- bici %>%
group_by(bici_estacion_origen, bici_estacion_destino) %>%
summarise(total = n())
Vamos a hacer un heatmap para evaluar el grado de interconexion, que muestre la cantidad de viaje entre pares.
ggplot() +
geom_tile(data = conteo, aes(x = bici_estacion_origen, y = bici_estacion_destino, fill = total)) +
scale_fill_distiller(palette = "Spectral")
La numeración discontinua de la estaciones dificulta la lectura del mismo.
Para evitar el bache en el mapa de calor vamos a tratar a las estaciones como una variable categórica (un factor) en lugar de numérica.
ggplot() +
geom_tile(data = conteo,
aes(x = as.factor(bici_estacion_origen),
y = as.factor(bici_estacion_destino),
fill = total)) +
scale_fill_distiller(palette = "Spectral")
La densidad del grafico hace dificil sacar conclusiones, pero podemos ver en la linea verde que la mayoria de los viajes empiezan y terminan en la misma estación. Podria ser por una cuestion recreativa, el usuario da una vuelta y la deja en el mismo lugar. Otra explicación podria ser que al sacarla ven que no esta en condiciones óptimas y deciden dejarla para agarrar otra. Esto último se podría verificar por ejemplo filtrando los viajes menores a 1 minuto.
Otra información que nos proporciona el gráfico es la concentración de puntos rojos (mucha cantidad) hacia el cero del eje de coordenadas, es decir proximo a la estación cero. Esto indica que estos viajes son en la zona centrica, donde se pusieron las primeras estaciones y por lo tanto la que tienen numero de serie menor.
Vamos a obtener los 30 viajes mas populares, descartando los viajes “circulares” (con el mismo origen y destino):
top30 <- conteo %>%
ungroup() %>%
filter(bici_estacion_origen != bici_estacion_destino) %>%
top_n(30)
## Selecting by total
top30
## # A tibble: 30 x 3
## bici_estacion_origen bici_estacion_destino total
## <int> <int> <int>
## 1 1 2 1111
## 2 1 103 1219
## 3 1 131 1408
## 4 2 1 932
## 5 5 14 1023
## 6 5 44 1307
## 7 5 160 1151
## 8 5 177 2213
## 9 9 30 967
## 10 9 66 1091
## # ... with 20 more rows
ggplot() +
geom_tile(data = top30,
aes(x = as.factor(bici_estacion_origen),
y = as.factor(bici_estacion_destino),
fill = total)) +
scale_fill_distiller(palette = "Spectral")
y el top 10
top10 <- conteo %>%
ungroup() %>%
filter(bici_estacion_origen != bici_estacion_destino) %>%
arrange(desc(total)) %>%
top_n(10)
## Selecting by total
top10
## # A tibble: 10 x 3
## bici_estacion_origen bici_estacion_destino total
## <int> <int> <int>
## 1 177 5 2323
## 2 5 177 2213
## 3 14 160 1560
## 4 1 131 1408
## 5 131 1 1407
## 6 26 131 1362
## 7 5 44 1307
## 8 103 1 1270
## 9 160 14 1253
## 10 14 159 1232
ggplot() +
geom_tile(data = top10,
aes(x = as.factor(bici_estacion_origen),
y = as.factor(bici_estacion_destino),
fill = total)) +
scale_fill_distiller(palette = "Spectral")
y el top 5
top5 <- conteo %>%
ungroup() %>%
filter(bici_estacion_origen != bici_estacion_destino) %>%
arrange(desc(total)) %>%
top_n(5)
## Selecting by total
top5
## # A tibble: 5 x 3
## bici_estacion_origen bici_estacion_destino total
## <int> <int> <int>
## 1 177 5 2323
## 2 5 177 2213
## 3 14 160 1560
## 4 1 131 1408
## 5 131 1 1407
Ahora vamos a mapear estos 5 viajes mas frecuentes
Primero hacemos un join del dataframe con el conteo de viajes contra el de posición de estaciones, para agregar las coordenadas
top10 <- top10 %>%
left_join(estaciones[c("long", "lat", "nombre", "nro_est")],
by = c("bici_estacion_origen" = "nro_est")) %>%
rename(ORIGEN_X = long,
ORIGEN_Y = lat,
ORIGEN_NOMBRE = nombre)
top10
## # A tibble: 10 x 6
## bici_estacion_or~ bici_estacion_d~ total ORIGEN_X ORIGEN_Y ORIGEN_NOMBRE
## <int> <int> <int> <dbl> <dbl> <fct>
## 1 177 5 2323 -58.4 -34.6 Planetario
## 2 5 177 2213 -58.4 -34.6 Plaza Italia
## 3 14 160 1560 -58.4 -34.6 Pacífico
## 4 1 131 1408 -58.4 -34.6 Facultad de ~
## 5 131 1 1407 -58.4 -34.6 Retiro III
## 6 26 131 1362 -58.4 -34.6 Juana Manso
## 7 5 44 1307 -58.4 -34.6 Plaza Italia
## 8 103 1 1270 -58.4 -34.6 Malba
## 9 160 14 1253 -58.4 -34.6 Godoy Cruz y~
## 10 14 159 1232 -58.4 -34.6 Pacífico
y hacemos lo propio con las estaciones de destino
top10 <- top10 %>%
left_join(estaciones[c("long", "lat", "nombre", "nro_est")],
by = c("bici_estacion_destino" = "nro_est")) %>%
rename(DESTINO_X = long,
DESTINO_Y = lat,
DESTINO_NOMBRE = nombre)
top10
## # A tibble: 10 x 9
## bici_estacion_o~ bici_estacion_d~ total ORIGEN_X ORIGEN_Y ORIGEN_NOMBRE
## <int> <int> <int> <dbl> <dbl> <fct>
## 1 177 5 2323 -58.4 -34.6 Planetario
## 2 5 177 2213 -58.4 -34.6 Plaza Italia
## 3 14 160 1560 -58.4 -34.6 Pacífico
## 4 1 131 1408 -58.4 -34.6 Facultad de ~
## 5 131 1 1407 -58.4 -34.6 Retiro III
## 6 26 131 1362 -58.4 -34.6 Juana Manso
## 7 5 44 1307 -58.4 -34.6 Plaza Italia
## 8 103 1 1270 -58.4 -34.6 Malba
## 9 160 14 1253 -58.4 -34.6 Godoy Cruz y~
## 10 14 159 1232 -58.4 -34.6 Pacífico
## # ... with 3 more variables: DESTINO_X <dbl>, DESTINO_Y <dbl>,
## # DESTINO_NOMBRE <fct>
Vamos a mapear el recorrido del viaje mas popular: Planetario - Pza. Italia
viaje <- top10[1,]
planet_a_italia <- osrmRoute(src = c(viaje$bici_estacion_origen, viaje$ORIGEN_X, viaje$ORIGEN_Y),
dst = c(viaje$bici_estacion_destino, viaje$DESTINO_X, viaje$DESTINO_Y),
sp = TRUE,
overview = "full")
## Warning: sp is deprecated; use returnclass instead.
planet_a_italia@data
## src dst duration distance
## 177_5 177 5 15.54667 2.0442
leaflet(planet_a_italia) %>%
addTiles() %>%
addPolylines(color = "blue")
Y los 4 siguientes para completar el top5
viaje2 <- top10[2,]
v2 <- osrmRoute(src = c(viaje2$bici_estacion_origen, viaje2$ORIGEN_X, viaje2$ORIGEN_Y),
dst = c(viaje2$bici_estacion_destino, viaje2$DESTINO_X, viaje2$DESTINO_Y),
sp = TRUE,
overview = "full")
## Warning: sp is deprecated; use returnclass instead.
v2@data
## src dst duration distance
## 5_177 5 177 16.85333 4.437
leaflet(v2) %>%
addTiles() %>%
addPolylines(color = "red")
viaje3 <- top10[3,]
v3 <- osrmRoute(src = c(viaje3$bici_estacion_origen, viaje3$ORIGEN_X, viaje3$ORIGEN_Y),
dst = c(viaje2$bici_estacion_destino, viaje3$DESTINO_X, viaje3$DESTINO_Y),
sp = TRUE,
overview = "full")
## Warning: sp is deprecated; use returnclass instead.
v3@data
## src dst duration distance
## 14_177 14 177 4.113333 1.0292
leaflet(v3) %>%
addTiles() %>%
addPolylines(color = "green")
viaje4 <- top10[4,]
v4 <- osrmRoute(src = c(viaje4$bici_estacion_origen, viaje4$ORIGEN_X, viaje4$ORIGEN_Y),
dst = c(viaje4$bici_estacion_destino, viaje4$DESTINO_X, viaje4$DESTINO_Y),
sp = TRUE,
overview = "full")
## Warning: sp is deprecated; use returnclass instead.
v4@data
## src dst duration distance
## 1_131 1 131 16.28833 5.3237
leaflet(v4) %>%
addTiles() %>%
addPolylines(color = "purple")
viaje5 <- top10[5,]
v5 <- osrmRoute(src = c(viaje5$bici_estacion_origen, viaje5$ORIGEN_X, viaje5$ORIGEN_Y),
dst = c(viaje5$bici_estacion_destino, viaje5$DESTINO_X, viaje5$DESTINO_Y),
sp = TRUE,
overview = "full")
## Warning: sp is deprecated; use returnclass instead.
v5@data
## src dst duration distance
## 131_1 131 1 8.363333 2.3975
leaflet(v5) %>%
addTiles() %>%
addPolylines(color = "cyan")