Si bien cuando vemos fechas las podemos entender fácilmente, estos campos suelen ser formatos difíciles de trabajar en R. Sin embargo, el paquete lubridate nos permite poder manipularlas mejor. Con este paquete, además de poder operar sobre las fechas, podemos también conocer los días de las semanas y los meses.
En primer lugar vamos a cargar las librerías. Recuerden instalarlas previamente con install.packages():
# install.packages("tidyverse")
library(tidyverse)
# install.packages("lubridate")
library(lubridate)
Vamos a trabajar con datos de Blue Bike, empresa prestataria de los servicios de bicicletas públicas en la ciudad de Boston, Massacusetts, USA. Se agregaron los datos de Enero a Abril 20201.
El dataset puede descargarse desde aqui.
También puede obtenerse desde una query a data.world:
bikes2021 <- read.csv(“https://query.data.world/s/lgh5y23j2ym4zvkhqfi4z75wqtxwnp”, header=TRUE)
bikes2021 <- read.csv("bikes.csv", header = TRUE)
En primer lugar vamos a inspeccionar nuestra base de datos:
head(bikes2021)
## tripduration starttime stoptime
## 1 914 2021-01-01 00:00:04.5900 2021-01-01 00:15:19.1680
## 2 1085 2021-01-01 00:00:21.8030 2021-01-01 00:18:27.4640
## 3 946 2021-01-01 00:00:26.0090 2021-01-01 00:16:12.0900
## 4 355 2021-01-01 00:00:30.9210 2021-01-01 00:06:26.6000
## 5 511 2021-01-01 00:01:11.2270 2021-01-01 00:09:43.1950
## 6 1004 2021-01-01 00:01:52.3100 2021-01-01 00:18:36.4180
## start.station.id start.station.name
## 1 91 One Kendall Square at Hampshire St / Portland St
## 2 370 Dartmouth St at Newbury St
## 3 46 Christian Science Plaza - Massachusetts Ave at Westland Ave
## 4 178 MIT Pacific St at Purrington St
## 5 386 Sennott Park Broadway at Norfolk Street
## 6 105 Lower Cambridgeport at Magazine St / Riverside Rd
## start.station.latitude start.station.longitude end.station.id
## 1 42.36628 -71.09169 370
## 2 42.35096 -71.07783 169
## 3 42.34367 -71.08582 21
## 4 42.35957 -71.10129 107
## 5 42.36861 -71.09930 413
## 6 42.35722 -71.11387 55
## end.station.name end.station.latitude
## 1 Dartmouth St at Newbury St 42.35096
## 2 Edwards Playground - Main St at Eden St 42.37897
## 3 Prudential Center - 101 Huntington Ave 42.34652
## 4 Ames St at Main St 42.36250
## 5 Kennedy-Longfellow School 158 Spring St 42.36955
## 6 Boylston St at Massachusetts Ave 42.34741
## end.station.longitude bikeid usertype postal.code
## 1 -71.07783 5316 Customer 02139
## 2 -71.06861 4917 Subscriber 02116
## 3 -71.08066 2881 Customer 02115
## 4 -71.08822 4792 Subscriber 02139
## 5 -71.08579 6062 Subscriber 02139
## 6 -71.08678 4371 Subscriber 02139
Existen tres tipos de formato de fechas:
- fecha
- hora
- fecha-hora
En nuestro dataset las variables starttime y stoptime están en formato fecha-hora. Sin embargo, R aún no las reconoce:
class(bikes2021$starttime)
## [1] "character"
Por el momento es una variable tipo caracter.
Veamos algunas funciones de fechas del paquete lubridate:
- today() : nos indica la fecha de hoy
- now(): nos indica la fecha y hora de ahora
today()
## [1] "2021-07-27"
class(today())
## [1] "Date"
Vemos que la clase es fecha.
now()
## [1] "2021-07-27 20:10:25 -03"
class(now())
## [1] "POSIXct" "POSIXt"
POSIXct es una clase de datos de fecha y hora.
Vamos a transformar nuestra variable starttime en formato fecha-hora. Para esto pueden utilizar multiples funciones de lubridate dependiendo de como estén escritos los campos. Vamos a mostrar algunas de ellas. Pueden ver otras maneras aquí
Para facilitar la lectura, vamos a tomar una muestra de 10 recorridos con la función sample_n() y vamos a seleccionar solo el campo starttime que vamos a renombrar como ‘original’
set.seed(1)
bikes_sample <- bikes2021 %>%
sample_n(10) %>%
select(starttime) %>%
rename(original = starttime)
bikes_sample
## original
## 1 2021-01-12 11:19:41.1070
## 2 2021-04-30 02:01:48.3390
## 3 2021-02-26 14:06:25.0460
## 4 2021-04-27 11:49:19.8170
## 5 2021-04-10 21:18:16.3310
## 6 2021-03-04 22:29:25.0680
## 7 2021-01-12 16:34:11.8430
## 8 2021-04-05 21:06:16.7970
## 9 2021-04-20 23:35:25.9130
## 10 2021-02-23 23:12:51.4980
Nuestro campo tiene fecha y hora. La fecha se encuentra en formato: año(year), mes(month), día(day), hora(hour), minuto(minute), segundo (second).
Se utiliza entonces la función ymd_hms().
bikes_sample <- bikes_sample %>%
mutate(fecha_hora = ymd_hms(original))
bikes_sample
## original fecha_hora
## 1 2021-01-12 11:19:41.1070 2021-01-12 11:19:41
## 2 2021-04-30 02:01:48.3390 2021-04-30 02:01:48
## 3 2021-02-26 14:06:25.0460 2021-02-26 14:06:25
## 4 2021-04-27 11:49:19.8170 2021-04-27 11:49:19
## 5 2021-04-10 21:18:16.3310 2021-04-10 21:18:16
## 6 2021-03-04 22:29:25.0680 2021-03-04 22:29:25
## 7 2021-01-12 16:34:11.8430 2021-01-12 16:34:11
## 8 2021-04-05 21:06:16.7970 2021-04-05 21:06:16
## 9 2021-04-20 23:35:25.9130 2021-04-20 23:35:25
## 10 2021-02-23 23:12:51.4980 2021-02-23 23:12:51
class(bikes_sample$fecha_hora)
## [1] "POSIXct" "POSIXt"
Podemos ver que la clase de la variable fecha_hora es de POSIXct (fecha - hora) .
Vamos a crear ahora un nuevo campo que solo contenga la fecha con la función substr()
bikes_sample <- bikes_sample %>%
mutate(solo_fecha = substr(original, 1, 10))
bikes_sample
## original fecha_hora solo_fecha
## 1 2021-01-12 11:19:41.1070 2021-01-12 11:19:41 2021-01-12
## 2 2021-04-30 02:01:48.3390 2021-04-30 02:01:48 2021-04-30
## 3 2021-02-26 14:06:25.0460 2021-02-26 14:06:25 2021-02-26
## 4 2021-04-27 11:49:19.8170 2021-04-27 11:49:19 2021-04-27
## 5 2021-04-10 21:18:16.3310 2021-04-10 21:18:16 2021-04-10
## 6 2021-03-04 22:29:25.0680 2021-03-04 22:29:25 2021-03-04
## 7 2021-01-12 16:34:11.8430 2021-01-12 16:34:11 2021-01-12
## 8 2021-04-05 21:06:16.7970 2021-04-05 21:06:16 2021-04-05
## 9 2021-04-20 23:35:25.9130 2021-04-20 23:35:25 2021-04-20
## 10 2021-02-23 23:12:51.4980 2021-02-23 23:12:51 2021-02-23
El nuevo campo que creamos está escrito en formato: año(year), mes(month), día(day).
Se utiliza entonces la función ymd().
bikes_sample <- bikes_sample %>%
mutate(fecha = ymd(solo_fecha))
bikes_sample
## original fecha_hora solo_fecha fecha
## 1 2021-01-12 11:19:41.1070 2021-01-12 11:19:41 2021-01-12 2021-01-12
## 2 2021-04-30 02:01:48.3390 2021-04-30 02:01:48 2021-04-30 2021-04-30
## 3 2021-02-26 14:06:25.0460 2021-02-26 14:06:25 2021-02-26 2021-02-26
## 4 2021-04-27 11:49:19.8170 2021-04-27 11:49:19 2021-04-27 2021-04-27
## 5 2021-04-10 21:18:16.3310 2021-04-10 21:18:16 2021-04-10 2021-04-10
## 6 2021-03-04 22:29:25.0680 2021-03-04 22:29:25 2021-03-04 2021-03-04
## 7 2021-01-12 16:34:11.8430 2021-01-12 16:34:11 2021-01-12 2021-01-12
## 8 2021-04-05 21:06:16.7970 2021-04-05 21:06:16 2021-04-05 2021-04-05
## 9 2021-04-20 23:35:25.9130 2021-04-20 23:35:25 2021-04-20 2021-04-20
## 10 2021-02-23 23:12:51.4980 2021-02-23 23:12:51 2021-02-23 2021-02-23
Por último, vamos a crear un último formato de fecha:
bikes_sample <- bikes_sample %>%
mutate(solo_fecha2 =
paste0(substr(solo_fecha,9,10), "/", substr(solo_fecha, 6,7), "/", substr(solo_fecha,1,4)))
bikes_sample
## original fecha_hora solo_fecha fecha
## 1 2021-01-12 11:19:41.1070 2021-01-12 11:19:41 2021-01-12 2021-01-12
## 2 2021-04-30 02:01:48.3390 2021-04-30 02:01:48 2021-04-30 2021-04-30
## 3 2021-02-26 14:06:25.0460 2021-02-26 14:06:25 2021-02-26 2021-02-26
## 4 2021-04-27 11:49:19.8170 2021-04-27 11:49:19 2021-04-27 2021-04-27
## 5 2021-04-10 21:18:16.3310 2021-04-10 21:18:16 2021-04-10 2021-04-10
## 6 2021-03-04 22:29:25.0680 2021-03-04 22:29:25 2021-03-04 2021-03-04
## 7 2021-01-12 16:34:11.8430 2021-01-12 16:34:11 2021-01-12 2021-01-12
## 8 2021-04-05 21:06:16.7970 2021-04-05 21:06:16 2021-04-05 2021-04-05
## 9 2021-04-20 23:35:25.9130 2021-04-20 23:35:25 2021-04-20 2021-04-20
## 10 2021-02-23 23:12:51.4980 2021-02-23 23:12:51 2021-02-23 2021-02-23
## solo_fecha2
## 1 12/01/2021
## 2 30/04/2021
## 3 26/02/2021
## 4 27/04/2021
## 5 10/04/2021
## 6 04/03/2021
## 7 12/01/2021
## 8 05/04/2021
## 9 20/04/2021
## 10 23/02/2021
El campo solo_fecha2 está en formato día(day), mes(month), año(year). Se utiliza entonces la función dmy().
bikes_sample <- bikes_sample %>%
mutate(fecha2 = dmy(solo_fecha2))
bikes_sample
## original fecha_hora solo_fecha fecha
## 1 2021-01-12 11:19:41.1070 2021-01-12 11:19:41 2021-01-12 2021-01-12
## 2 2021-04-30 02:01:48.3390 2021-04-30 02:01:48 2021-04-30 2021-04-30
## 3 2021-02-26 14:06:25.0460 2021-02-26 14:06:25 2021-02-26 2021-02-26
## 4 2021-04-27 11:49:19.8170 2021-04-27 11:49:19 2021-04-27 2021-04-27
## 5 2021-04-10 21:18:16.3310 2021-04-10 21:18:16 2021-04-10 2021-04-10
## 6 2021-03-04 22:29:25.0680 2021-03-04 22:29:25 2021-03-04 2021-03-04
## 7 2021-01-12 16:34:11.8430 2021-01-12 16:34:11 2021-01-12 2021-01-12
## 8 2021-04-05 21:06:16.7970 2021-04-05 21:06:16 2021-04-05 2021-04-05
## 9 2021-04-20 23:35:25.9130 2021-04-20 23:35:25 2021-04-20 2021-04-20
## 10 2021-02-23 23:12:51.4980 2021-02-23 23:12:51 2021-02-23 2021-02-23
## solo_fecha2 fecha2
## 1 12/01/2021 2021-01-12
## 2 30/04/2021 2021-04-30
## 3 26/02/2021 2021-02-26
## 4 27/04/2021 2021-04-27
## 5 10/04/2021 2021-04-10
## 6 04/03/2021 2021-03-04
## 7 12/01/2021 2021-01-12
## 8 05/04/2021 2021-04-05
## 9 20/04/2021 2021-04-20
## 10 23/02/2021 2021-02-23
Podemos observar que las variables fecha y fecha2 son iguales. El formato default para las fechas de R es año-mes-día.
Supongamos ahora que los valores de año, mes y día están separados:
bikes_sample2 <- bikes_sample %>%
select(original) %>%
mutate(anio = substr(original, 1,4), #evitamos la ñ en R, a veces se generan errores
mes= substr(original, 6,7),
dia = substr(original, 9,10))
bikes_sample2
## original anio mes dia
## 1 2021-01-12 11:19:41.1070 2021 01 12
## 2 2021-04-30 02:01:48.3390 2021 04 30
## 3 2021-02-26 14:06:25.0460 2021 02 26
## 4 2021-04-27 11:49:19.8170 2021 04 27
## 5 2021-04-10 21:18:16.3310 2021 04 10
## 6 2021-03-04 22:29:25.0680 2021 03 04
## 7 2021-01-12 16:34:11.8430 2021 01 12
## 8 2021-04-05 21:06:16.7970 2021 04 05
## 9 2021-04-20 23:35:25.9130 2021 04 20
## 10 2021-02-23 23:12:51.4980 2021 02 23
Las funciones make_date() y make_datetime() nos permiten unir los campos rápidamente. Como no tenemos hora, vamos a usar make_date().
bikes_sample2 <- bikes_sample2 %>%
mutate(fecha = make_date(year= anio, month = mes, day = dia))
bikes_sample2
## original anio mes dia fecha
## 1 2021-01-12 11:19:41.1070 2021 01 12 2021-01-12
## 2 2021-04-30 02:01:48.3390 2021 04 30 2021-04-30
## 3 2021-02-26 14:06:25.0460 2021 02 26 2021-02-26
## 4 2021-04-27 11:49:19.8170 2021 04 27 2021-04-27
## 5 2021-04-10 21:18:16.3310 2021 04 10 2021-04-10
## 6 2021-03-04 22:29:25.0680 2021 03 04 2021-03-04
## 7 2021-01-12 16:34:11.8430 2021 01 12 2021-01-12
## 8 2021-04-05 21:06:16.7970 2021 04 05 2021-04-05
## 9 2021-04-20 23:35:25.9130 2021 04 20 2021-04-20
## 10 2021-02-23 23:12:51.4980 2021 02 23 2021-02-23
Podríamos no tener alguna de las variables, y en ese caso agregarla nosotros. Por ejemplo, si no tuviesemos el año, pero sabemos que son datos del 2021, lo podríamos incorporar nosotros.
bikes_sample2 <- bikes_sample2 %>%
mutate(fecha2 = make_date(year= 2021, month = mes, day = dia))
bikes_sample2
## original anio mes dia fecha fecha2
## 1 2021-01-12 11:19:41.1070 2021 01 12 2021-01-12 2021-01-12
## 2 2021-04-30 02:01:48.3390 2021 04 30 2021-04-30 2021-04-30
## 3 2021-02-26 14:06:25.0460 2021 02 26 2021-02-26 2021-02-26
## 4 2021-04-27 11:49:19.8170 2021 04 27 2021-04-27 2021-04-27
## 5 2021-04-10 21:18:16.3310 2021 04 10 2021-04-10 2021-04-10
## 6 2021-03-04 22:29:25.0680 2021 03 04 2021-03-04 2021-03-04
## 7 2021-01-12 16:34:11.8430 2021 01 12 2021-01-12 2021-01-12
## 8 2021-04-05 21:06:16.7970 2021 04 05 2021-04-05 2021-04-05
## 9 2021-04-20 23:35:25.9130 2021 04 20 2021-04-20 2021-04-20
## 10 2021-02-23 23:12:51.4980 2021 02 23 2021-02-23 2021-02-23
Vamos a retomar nuestro dataset original para transformar los campos starttime y stoptime a fecha-hora. Vamos a seleccionar los campos bikeid, usertype y los dos nuevos campos de fecha.
bikes2021_modificada <- bikes2021 %>%
mutate(inicio= ymd_hms(starttime),
final = ymd_hms(stoptime)) %>%
select(bikeid, usertype, tripduration, inicio, final)
Ahora que ya sabemos transformar los datos a formato fecha, vamos a utilizar otras funciones de ‘lubridate’. Por ejemplo, la función round_date() nos permite redondear la fecha. La vamos a usar para ver la evolución de la cantidad de viajes diarios.
viajes_por_dia <- bikes2021_modificada %>%
mutate(dia = round_date(inicio, "day")) %>%
group_by(dia) %>%
summarise(cantidad =n())
## `summarise()` ungrouping output (override with `.groups` argument)
head(viajes_por_dia)
## # A tibble: 6 x 2
## dia cantidad
## <dttm> <int>
## 1 2021-01-01 00:00:00 525
## 2 2021-01-02 00:00:00 1608
## 3 2021-01-03 00:00:00 1811
## 4 2021-01-04 00:00:00 1371
## 5 2021-01-05 00:00:00 2101
## 6 2021-01-06 00:00:00 2030
viajes_por_dia %>%
ggplot() +
geom_line(aes(x=dia, y = cantidad), color = "darkslateblue") +
labs(title = "Viajes por día",
subtitle = "Boston 2021",
caption = "Fuente: BlueBike",
x = "",
y = "") +
scale_y_continuous(breaks = seq(0, 16000, 1000)) +
theme_minimal()
Vamos a utilizar otras funciones para poder explorar mejor los datos.
Las funciones year(), month(), day(), hour(), minute(), y second() nos permiten extraer ese componente de la fecha.
A partir de estas funciones, vamos a evaluar la cantidad de recorridos por mes de inicio, y por hora inicial y final.
bikes2021_modificada <- bikes2021_modificada %>%
mutate(mes = month(inicio),
hora_inicial = hour(inicio),
hora_final = hour(final))
head(bikes2021_modificada)
## bikeid usertype tripduration inicio final mes
## 1 5316 Customer 914 2021-01-01 00:00:04 2021-01-01 00:15:19 1
## 2 4917 Subscriber 1085 2021-01-01 00:00:21 2021-01-01 00:18:27 1
## 3 2881 Customer 946 2021-01-01 00:00:26 2021-01-01 00:16:12 1
## 4 4792 Subscriber 355 2021-01-01 00:00:30 2021-01-01 00:06:26 1
## 5 6062 Subscriber 511 2021-01-01 00:01:11 2021-01-01 00:09:43 1
## 6 4371 Subscriber 1004 2021-01-01 00:01:52 2021-01-01 00:18:36 1
## hora_inicial hora_final
## 1 0 0
## 2 0 0
## 3 0 0
## 4 0 0
## 5 0 0
## 6 0 0
Si bien nosotros sabemos que el mes 1 es enero, prefeririamos verlo en texto. Dentro de la función month() se encuentran los parámetros ‘label’ y ‘abb’.
Veamos un ejemplo con today():
month(today())
## [1] 7
month(today(), label = TRUE)
## [1] Jul
## 12 Levels: Jan < Feb < Mar < Apr < May < Jun < Jul < Aug < Sep < ... < Dec
Como pueden ver, los textos están en inglés. Los queremos en español y no los queremos abreviados.
month(today(), label = TRUE, abbr = FALSE, locale = "es_ES.UTF-8")
## [1] julio
## 12 Levels: enero < febrero < marzo < abril < mayo < junio < ... < diciembre
#para Windows utilizar: "Spanish"
¡Perfecto! Ahora volvamos a nuestra base:
bikes2021_modificada <- bikes2021_modificada %>%
mutate(mes = month(inicio, abbr = FALSE, label = TRUE, locale = "es_ES.UTF-8"),
hora_inicial = hour(inicio),
hora_final = hour(final))
head(bikes2021_modificada)
## bikeid usertype tripduration inicio final mes
## 1 5316 Customer 914 2021-01-01 00:00:04 2021-01-01 00:15:19 enero
## 2 4917 Subscriber 1085 2021-01-01 00:00:21 2021-01-01 00:18:27 enero
## 3 2881 Customer 946 2021-01-01 00:00:26 2021-01-01 00:16:12 enero
## 4 4792 Subscriber 355 2021-01-01 00:00:30 2021-01-01 00:06:26 enero
## 5 6062 Subscriber 511 2021-01-01 00:01:11 2021-01-01 00:09:43 enero
## 6 4371 Subscriber 1004 2021-01-01 00:01:52 2021-01-01 00:18:36 enero
## hora_inicial hora_final
## 1 0 0
## 2 0 0
## 3 0 0
## 4 0 0
## 5 0 0
## 6 0 0
Vamos a hacer un gráfico .
bikes2021_modificada %>%
ggplot() +
geom_bar(aes( x= mes, fill = mes)) +
labs(title = "Recorridos en bicicleta por mes",
subtitle = "Boston 2021",
caption = "Fuente: BlueBike",
x = "Mes",
y = "Cantidad (en miles)") +
scale_fill_brewer(palette = 8, type = "qual") +
scale_y_continuous(breaks =seq(0,200000, 20000), labels = seq(0, 200, 20)) +
theme_minimal() +
theme(legend.position = "none")
Podríamos haber hecho el gráfico sin crear la nueva categoría ‘mes’:
bikes2021_modificada %>%
ggplot() +
geom_bar(aes( x= month(inicio, abbr = FALSE, label = TRUE, locale = "es_ES.UTF-8"), fill = mes)) +
labs(title = "Recorridos en bicicleta por mes",
subtitle = "Boston 2021",
caption = "Fuente: BlueBike",
x = "Mes",
y = "Cantidad (en miles)") +
scale_fill_brewer(palette = 8, type = "qual") +
scale_y_continuous(breaks =seq(0,200000, 20000), labels = seq(0, 200, 20)) +
theme_minimal() +
theme(legend.position = "none")
Ahora vamos a ver la distribución por hora de inicio del recorrido:
bikes2021_modificada %>%
ggplot() +
geom_bar(aes(x=hora_inicial)) +
labs(title = "Recorridos en bicicleta por hora",
subtitle = "Boston - Enero a Abril 2021",
caption = "Fuente: BlueBike",
x = "Hora de inicio",
y = "Cantidad (en miles)") +
scale_y_continuous(breaks =seq(0,40000, 5000), labels = seq(0, 40, 5)) +
theme_minimal()
¿La distribución depende del tipo de usuario?
bikes2021_modificada %>%
ggplot() +
geom_bar(aes(x=hora_inicial, fill = usertype)) +
labs(title = "Recorridos en bicicleta por hora",
subtitle = "Boston - Enero a Abril 2021",
caption = "Fuente: BlueBike",
fill = "Tipo de usuario",
x = "Hora de inicio",
y = "Cantidad (en miles)") +
scale_y_continuous(breaks =seq(0,40000, 5000), labels = seq(0, 40, 5)) +
scale_fill_manual(values = c("darkolivegreen4", "darkslategray3"), labels = c("Cliente", "Abonado")) +
theme_minimal()
¿El patrón es similar para la hora de final de recorrido?
bikes2021_modificada %>%
ggplot() +
geom_bar(aes(x=hora_final, fill = usertype)) +
labs(title = "Recorridos en bicicleta por hora",
subtitle = "Boston - Enero a Abril 2021",
caption = "Fuente: BlueBike",
fill = "Tipo de usuario",
x = "Hora de finalización",
y = "Cantidad (en miles)") +
scale_y_continuous(breaks =seq(0,40000, 5000), labels = seq(0, 40, 5)) +
scale_fill_manual(values = c("darkolivegreen4", "darkslategray3"), labels = c("Cliente", "Abonado")) +
theme_minimal()
Necesitamos modificar el dataset para que la comparación sea más sencilla. Para eso vamos a usar la función gather(). Aquí pueden ver como utilizar las funciones gather() y spread().
bikes2021_modificada %>%
select(hora_inicial, hora_final) %>%
gather(key = "tipo", value = "hora", 1:2) %>%
ggplot() +
geom_bar(aes(x=hora, fill=tipo), position = position_dodge(preserve = "single")) +
labs(title = "Recorridos en bicicleta por hora",
subtitle = "Boston - Enero a Abril 2021",
caption = "Fuente: BlueBike",
fill = "",
x = "Hora",
y = "Cantidad (en miles)") +
scale_y_continuous(breaks =seq(0,40000, 5000), labels = seq(0, 40, 5)) +
scale_x_continuous(breaks = seq(0,23,1)) +
scale_fill_manual(values = c("darkolivegreen4", "darkslategray3"), labels = c("Final", "Inicial")) +
theme_minimal()
También podríamos verlo con un gráfino de líneas. Para ello vamos a realizar un conteo por hora de inicio y por hora de finalización
df_hora <- bikes2021_modificada %>%
gather(key = "tipo", value = "hora", hora_inicial, hora_final) %>%
group_by(hora, tipo) %>%
summarise(duracion_promedio = round(mean(tripduration)/60, digits = 0),
cantidad =n())
## `summarise()` regrouping output by 'hora' (override with `.groups` argument)
head(df_hora)
## # A tibble: 6 x 4
## # Groups: hora [3]
## hora tipo duracion_promedio cantidad
## <int> <chr> <dbl> <int>
## 1 0 hora_final 25 23233
## 2 0 hora_inicial 26 20362
## 3 1 hora_final 33 15416
## 4 1 hora_inicial 26 14155
## 5 2 hora_final 32 10971
## 6 2 hora_inicial 29 10340
Ahora si, a graficar:
ggplot() +
geom_line(data = df_hora , aes(x = hora, y =cantidad, color = tipo)) +
labs(title = "Recorridos en bicicleta por hora",
subtitle = "Boston - Enero a Abril 2021",
caption = "Fuente: BlueBike",
color = "Hora",
x = "Hora",
y = "Cantidad (en miles)") +
scale_y_continuous(breaks =seq(0,40000, 5000), labels = seq(0, 40, 5)) +
scale_x_continuous(breaks = seq(0,23,1)) +
scale_color_manual(values = c("darkolivegreen4", "darkslategray3"), labels = c("Final", "Inicial")) +
theme_minimal()
Ahora veamos la duración promedio de los recorridos:
ggplot() +
geom_line(data = df_hora , aes(x = hora, y =duracion_promedio, color = tipo)) +
labs(title = "Recorridos en bicicleta por hora",
subtitle = "Boston - Enero a Abril 2021",
caption = "Fuente: BlueBike",
color = "Hora",
x = "Hora",
y = "Duracion (en minutos)") +
scale_x_continuous(breaks = seq(0,23,1)) +
scale_color_manual(values = c("darkolivegreen4", "darkslategray3"), labels = c("Final", "Inicial")) +
theme_minimal()
Podemos observar un patrón en la cantidad de viajes por hora, y alteraciones en la duración promedio. Vamos a analizar a continuación que ocurre según el día de la semana. Para ello, vamos a utilizar la función wday() que permite obtener el día de la semana.
Probemosla con nuestra muestra anterior:
wday(bikes_sample$fecha)
## [1] 3 6 6 3 7 5 3 2 3 3
Al igual que la función mes, nos dice el número de día. Es poco intuitivo, asi que vamos a usar ‘abbr’ y ‘label’.
wday(bikes_sample$fecha, abbr = FALSE, label = TRUE, locale ="es_ES.UTF-8" )
## [1] martes viernes viernes martes sábado jueves martes lunes martes
## [10] martes
## 7 Levels: domingo < lunes < martes < miércoles < jueves < ... < sábado
Investiguemos la cantidad de viajes por día:
bikes2021_modificada %>%
ggplot() +
geom_bar(aes( x= wday(inicio, abbr = FALSE, label = TRUE, locale = "es_ES.UTF-8"), fill = wday(inicio))) +
labs(title = "Recorridos en bicicleta por mes",
subtitle = "Boston - Enero a Abril 2021",
caption = "Fuente: BlueBike",
x = "Día de la semana",
y = "Cantidad (en miles)") +
scale_fill_distiller(palette = 8, type = "qual") +
scale_y_continuous(breaks =seq(0,200000, 20000), labels = seq(0, 200, 20)) +
theme_minimal() +
theme(legend.position = "none")
## Warning: Using a discrete colour palette in a continuous scale.
## Consider using type = "seq" or type = "div" instead
Veamos la variabilidad por mes:
bikes2021_modificada %>%
ggplot() +
geom_bar(aes( x= wday(inicio, abbr = FALSE, label = TRUE, locale = "es_ES.UTF-8"), fill = wday(inicio))) +
labs(title = "Recorridos en bicicleta por mes",
subtitle = "Boston - Enero a Abril 2021",
caption = "Fuente: BlueBike",
x = "Día de la semana",
y = "Cantidad (en miles)") +
scale_fill_distiller(palette = 8, type = "qual") +
scale_y_continuous(breaks =seq(0,40000, 5000), labels = seq(0, 40, 5)) +
theme_minimal() +
theme(legend.position = "none") +
facet_wrap(~month(inicio, label = TRUE, abbr = FALSE, locale = "es_ES.UTF-8"))
## Warning: Using a discrete colour palette in a continuous scale.
## Consider using type = "seq" or type = "div" instead
Excepto en el mes de Abril, no parecería haber variabilidad según el día de la semana.
Por último, queremos evaluar como se comporta la duración de recorridos en relación a si se trata de un fin de semana o no. Si bien contamos contamos con la variable tripduration en segundos, vamos a generar un nuevo cálculo a partir de la función time_length() del paquete lubridate
bikes2021_modificada <- bikes2021_modificada %>%
mutate(duracion = round(time_length(final - inicio, unit = "minutes"), digits = 1))
head(bikes2021_modificada$duracion)
## [1] 15.2 18.1 15.8 5.9 8.5 16.7
Primero vamos a ver la distribución de la duración.
bikes2021_modificada%>%
ggplot() +
geom_boxplot(aes(y=duracion, x = ""))
Uno de los recorridos superó los 50.000min es decir las 833 horas o los 34 días. Nos parece muy poco probable que alguien esté utilizando la bicicleta durante tanto tiempo.
Vamos a filtrar registros inferiores a 2 horas o los 120 minutos.
bikes2021_modificada%>%
filter(duracion <= 120) %>%
ggplot() +
geom_boxplot(aes(y=duracion, x = "")) +
labs(title = "Duración de los recorridos",
y = "Duración (min)",
x = "") +
scale_y_continuous(breaks = seq(0,130,20)) +
theme_minimal()
La gran mayoría de los registros se encuentra por debajo de los 50min. ¿Esta distribución depende del día de la semana?
bikes2021_modificada%>%
filter(duracion <= 120) %>%
ggplot() +
geom_boxplot(aes(x = wday(inicio, abbr = FALSE, label = TRUE, locale = "es_ES.UTF-8"),
y=duracion,
fill = as.character(wday(inicio)))) +
labs(title = "Duración de los recorridos",
y = "Duración (min)",
x = "Día de inicio") +
theme_minimal() +
scale_y_continuous(breaks = seq(0,130,20)) +
scale_fill_brewer(palette = 8, type = "qual") +
theme(legend.position = "none")
Podemos modificar el día de inicio de la semana, ya que preferimos que sea lunes.
bikes2021_modificada%>%
filter(duracion <= 120) %>%
ggplot() +
geom_boxplot(aes(x = wday(inicio, abbr = FALSE, label = TRUE, locale = "es_ES.UTF-8", week_start = 1),
y=duracion,
fill = as.character(wday(inicio)))) +
labs(title = "Duración de los recorridos",
y = "Duración (min)",
x = "Día de inicio") +
theme_minimal() +
scale_y_continuous(breaks = seq(0,130,20)) +
scale_fill_brewer(palette = 8, type = "qual") +
theme(legend.position = "none")
Podemos observar que el valor medio de los viajes es muy similar para los días de semana, y el comportamiento difiere levemente los fin de semana.
¡Como vieron, con el paque ‘lubridate’ podemos trabajar sencillamente con las variables de tipo fecha!
Podemos hacer un gráfico animado (gif)
gif <- function() {
iterseq <- seq(0,23,1)
for (i in iterseq) {
plot <- ggplot() +
geom_line(data = df_hora , aes(x = hora, y =duracion_promedio, color = tipo)) +
geom_point(data = df_hora %>% filter(hora == i),
aes(x = i, y = duracion_promedio, color = tipo), size = 4) +
labs(title = "Recorridos en bicicleta por hora",
subtitle = "Boston - Enero a Abril 2021",
caption = "Fuente: BlueBike",
color = "Hora",
x = "Hora",
y = "Duracion (en minutos)") +
scale_x_continuous(breaks = seq(0,23,1)) +
scale_color_manual(values = c("darkolivegreen4", "darkslategray3"),
labels = c("Final", "Inicial")) +
theme_minimal()
print(plot)
}
}
Cargamos la librería para guardar y leer gif:
#install.packages("gifski")
library(gifski)
Ahora guardamos el gif
save_gif(gif(), "grafico_animado.gif", delay = 0.5, width = 600, height = 400, progress = FALSE)
knitr::include_graphics("grafico_animado.gif")