Capítulo24 Fechas, horas y minutas
Fecha de la ultima revisión
## [1] "2024-11-07"
El tema proviene de los siguientes sitios.
English: https://r4ds.had.co.nz/dates-and-times.html
Español: https://es.r4ds.hadley.nz/16-datetimes.html
24.2 Creando fechas/horas
- date,
- time,
- date-time,
https://github.com/edgararuiz/guias-rapidas/blob/master/fechas.pdf
library(tidyverse)
library(lubridate) # paquete para convertir fechas
tidyverse_packages() # lista completa de los paquetes activado con **tidyverse**
## [1] "broom" "conflicted" "cli" "dbplyr"
## [5] "dplyr" "dtplyr" "forcats" "ggplot2"
## [9] "googledrive" "googlesheets4" "haven" "hms"
## [13] "httr" "jsonlite" "lubridate" "magrittr"
## [17] "modelr" "pillar" "purrr" "ragg"
## [21] "readr" "readxl" "reprex" "rlang"
## [25] "rstudioapi" "rvest" "stringr" "tibble"
## [29] "tidyr" "xml2" "tidyverse"
24.3 El paquete lubridate
La función today()
regresa la fecha de hoy, similar a Sys.date()
## [1] "2024-11-07"
Use la función de tribble()
, del paquete tibble
, para crear una tabla manualmente
fechas <- tribble(
~ codigo, ~ fecha,
"001", "01/01/2019 00:00:00",
"002", "31/03/2019 01:05:00",
"003", "14/06/2019 20:00:00",
"004", "01/12/1859 11:32:13",
"005", "01/01/0501 05:04:33"
)
fechas
## # A tibble: 5 × 2
## codigo fecha
## <chr> <chr>
## 1 001 01/01/2019 00:00:00
## 2 002 31/03/2019 01:05:00
## 3 003 14/06/2019 20:00:00
## 4 004 01/12/1859 11:32:13
## 5 005 01/01/0501 05:04:33
Hay varias opciones para convertir texto a fechas, el más usado es mdy_hms()
, pero en este caso el formato utilizado no funciona bien.
24.3.1 Un error tipico
## # A tibble: 5 × 2
## codigo fecha
## <chr> <dttm>
## 1 001 2019-01-01 00:00:00
## 2 002 NA
## 3 003 NA
## 4 004 1859-01-12 11:32:13
## 5 005 0501-01-01 05:04:33
Ya que el día es el primero, y no el mes, usamos dmy_hms()
## # A tibble: 5 × 2
## codigo fecha
## <chr> <dttm>
## 1 001 2019-01-01 00:00:00
## 2 002 2019-03-31 01:05:00
## 3 003 2019-06-14 20:00:00
## 4 004 1859-12-01 11:32:13
## 5 005 0501-01-01 05:04:33
lubridate
tiene varias funciones para extraer partes de la fecha, por ejemplo: año, mes, día, hora, minuto, y quatrimestre.
nueva_fechas %>%
mutate(a = year(fecha),
m = month(fecha),
d = day(fecha),
h = hour(fecha),
mn = minute(fecha),
q = quarter(fecha)
)
## # A tibble: 5 × 8
## codigo fecha a m d h mn q
## <chr> <dttm> <int> <int> <int> <int> <int> <int>
## 1 001 2019-01-01 00:00:00 2019 1 1 0 0 1
## 2 002 2019-03-31 01:05:00 2019 3 31 1 5 1
## 3 003 2019-06-14 20:00:00 2019 6 14 20 0 2
## 4 004 1859-12-01 11:32:13 1859 12 1 11 32 4
## 5 005 0501-01-01 05:04:33 501 1 1 5 4 1
Las funciones round_date()
, ceiling_date()
y floor_date()
permiten redondear la fecha al número más cercano de la unidad especificada
nueva_fechas %>%
mutate(
redondear = round_date(fecha, unit = " month"), # redondea al mes más cercano
techo = ceiling_date(fecha, unit = "day"), # redondea al día más cercano
suelo = floor_date(fecha, unit = "month"), # redondea al mes más cercano
suelo_hour= floor_date(fecha, unit = "hour") # redondea a la hora más cercana
)
## # A tibble: 5 × 6
## codigo fecha redondear techo
## <chr> <dttm> <dttm> <dttm>
## 1 001 2019-01-01 00:00:00 2019-01-01 00:00:00 2019-01-01 00:00:00
## 2 002 2019-03-31 01:05:00 2019-04-01 00:00:00 2019-04-01 00:00:00
## 3 003 2019-06-14 20:00:00 2019-06-01 00:00:00 2019-06-15 00:00:00
## 4 004 1859-12-01 11:32:13 1859-12-01 00:00:00 1859-12-02 00:00:00
## 5 005 0501-01-01 05:04:33 0501-01-01 00:00:00 0501-01-02 00:00:00
## # ℹ 2 more variables: suelo <dttm>, suelo_hour <dttm>
24.4 Intervalos y duraciones
La función interval()
crea un objeto R de intervalo de tiempo. En este caso, el intervalo entro la fecha en la tabla, y el día de hoy. Nota que esto puede ser muy util si quiere calcular la cantidad de tiempo entre dos fechas.
## # A tibble: 5 × 3
## codigo fecha intervalo
## <chr> <dttm> <Interval>
## 1 001 2019-01-01 00:00:00 2019-01-01 00:00:00 UTC--2024-11-07 UTC
## 2 002 2019-03-31 01:05:00 2019-03-31 01:05:00 UTC--2024-11-07 UTC
## 3 003 2019-06-14 20:00:00 2019-06-14 20:00:00 UTC--2024-11-07 UTC
## 4 004 1859-12-01 11:32:13 1859-12-01 11:32:13 UTC--2024-11-07 UTC
## 5 005 0501-01-01 05:04:33 0501-01-01 05:04:33 UTC--2024-11-07 UTC
int_length()
regresa el número de segundos dentro del intervalo
nueva_fechas %>%
mutate(
intervalo = interval(fecha, today()), #
segundos = int_length(intervalo) # número de segundos en el intervalo
)
## # A tibble: 5 × 4
## codigo fecha intervalo segundos
## <chr> <dttm> <Interval> <dbl>
## 1 001 2019-01-01 00:00:00 2019-01-01 00:00:00 UTC--2024-11-07 UTC 184636800
## 2 002 2019-03-31 01:05:00 2019-03-31 01:05:00 UTC--2024-11-07 UTC 176943300
## 3 003 2019-06-14 20:00:00 2019-06-14 20:00:00 UTC--2024-11-07 UTC 170395200
## 4 004 1859-12-01 11:32:13 1859-12-01 11:32:13 UTC--2024-11-07 UTC 5204867267
## 5 005 0501-01-01 05:04:33 0501-01-01 05:04:33 UTC--2024-11-07 UTC 48088061727
24.5 El operador %--%
simplifica el cálculo del intervalo
Compara con el script anterior
## # A tibble: 5 × 3
## codigo fecha intervalo
## <chr> <dttm> <Interval>
## 1 001 2019-01-01 00:00:00 2019-01-01 00:00:00 UTC--2024-11-07 UTC
## 2 002 2019-03-31 01:05:00 2019-03-31 01:05:00 UTC--2024-11-07 UTC
## 3 003 2019-06-14 20:00:00 2019-06-14 20:00:00 UTC--2024-11-07 UTC
## 4 004 1859-12-01 11:32:13 1859-12-01 11:32:13 UTC--2024-11-07 UTC
## 5 005 0501-01-01 05:04:33 0501-01-01 05:04:33 UTC--2024-11-07 UTC
Para saber el número del días en el intervalo, divida el intervalo por la función que corresponde a días, days()
nueva_fechas %>%
mutate(dias = fecha %--% today() / days(),
anio= fecha %--% today() / years()) # número de días en el intervalo
## # A tibble: 5 × 4
## codigo fecha dias anio
## <chr> <dttm> <dbl> <dbl>
## 1 001 2019-01-01 00:00:00 2137 5.85
## 2 002 2019-03-31 01:05:00 2048. 5.61
## 3 003 2019-06-14 20:00:00 1972. 5.40
## 4 004 1859-12-01 11:32:13 60242. 165.
## 5 005 0501-01-01 05:04:33 556575. 1524.
Intervalo entre una lista de fecha y otra fecha y hora
## # A tibble: 5 × 3
## codigo fecha dias
## <chr> <dttm> <dbl>
## 1 001 2019-01-01 00:00:00 365
## 2 002 2019-03-31 01:05:00 276.
## 3 003 2019-06-14 20:00:00 200.
## 4 004 1859-12-01 11:32:13 58470.
## 5 005 0501-01-01 05:04:33 554803.
24.6 Ejercicio
Usa esta función y calcula el número de día que ha transcurido entre el día de su nacimiento y el dia de hoy
## [1] 2277
## [1] 196732800000
Los resultados se pueden visualizar usando ggplot2
24.7 Serie de funciones para calcular la duración de un intervalo de tiempo.
- dyears() # años
- dmonths() # meses
- dweeks() # semanas
- ddays() # días
- dhours() # horas
- dminutes() # minutos
- dseconds() # segundos
- dmilliseconds() # milisegundos
- dmicroseconds() # microsegundos
- dnanoseconds() # nanosegundos
- dpicoseconds() # picosegundos
24.8 as.duration
as.duration()
crea un objecto en R que contiene la duración del intervalo de tiempo.
nueva_fechas %>%
mutate(desde_hoy = as.duration(fecha %--% today())) # duración desde la fecha hasta hoy
## # A tibble: 5 × 3
## codigo fecha desde_hoy
## <chr> <dttm> <Duration>
## 1 001 2019-01-01 00:00:00 184636800s (~5.85 years)
## 2 002 2019-03-31 01:05:00 176943300s (~5.61 years)
## 3 003 2019-06-14 20:00:00 170395200s (~5.4 years)
## 4 004 1859-12-01 11:32:13 5204867267s (~164.93 years)
## 5 005 0501-01-01 05:04:33 48088061727s (~1523.82 years)
El objeto de duración de tiempo se puede filtrar fácilmente basado en una variedad de tipo de tiempos. En este caso, semanas dweeks()
crea un objeto de duración de la largura especificada
nueva_fechas %>%
mutate(desde_hoy = as.duration(fecha %--% today())) %>%
filter(desde_hoy < ddays(2000))
## # A tibble: 1 × 3
## codigo fecha desde_hoy
## <chr> <dttm> <Duration>
## 1 003 2019-06-14 20:00:00 170395200s (~5.4 years)
## [1] 1825
Otra opción es ddays()
.
nueva_fechas %>%
mutate(desde_hoy = as.duration(fecha %--% today())) %>%
filter(desde_hoy < ddays(2500)) # Nota que se puede filtrar por el número de días que han acumulado
## # A tibble: 3 × 3
## codigo fecha desde_hoy
## <chr> <dttm> <Duration>
## 1 001 2019-01-01 00:00:00 184636800s (~5.85 years)
## 2 002 2019-03-31 01:05:00 176943300s (~5.61 years)
## 3 003 2019-06-14 20:00:00 170395200s (~5.4 years)
24.9 Crear una fecha desde columnas individuales
- make_date()
- make_datetime()
Unir el año, mes, día, hora y minutos que estén en diferentes columnas en uno
- sumamente practico cuando se tiene una base de datos con las fechas en diferentes columnas
## # A tibble: 6 × 19
## anio mes dia horario_salida salida_programada atraso_salida
## <int> <int> <int> <int> <int> <dbl>
## 1 2013 1 1 517 515 2
## 2 2013 1 1 533 529 4
## 3 2013 1 1 542 540 2
## 4 2013 1 1 544 545 -1
## 5 2013 1 1 554 600 -6
## 6 2013 1 1 554 558 -4
## # ℹ 13 more variables: horario_llegada <int>, llegada_programada <int>,
## # atraso_llegada <dbl>, aerolinea <chr>, vuelo <int>, codigo_cola <chr>,
## # origen <chr>, destino <chr>, tiempo_vuelo <dbl>, distancia <dbl>,
## # hora <dbl>, minuto <dbl>, fecha_hora <dttm>
vuelos %>%
dplyr::select(anio, mes, dia, hora, minuto) %>%
mutate(salida_dia=make_date(anio, mes, dia),
salida_dia_minutos = make_datetime(anio, mes, dia, hora, minuto))
## # A tibble: 336,776 × 7
## anio mes dia hora minuto salida_dia salida_dia_minutos
## <int> <int> <int> <dbl> <dbl> <date> <dttm>
## 1 2013 1 1 5 15 2013-01-01 2013-01-01 05:15:00
## 2 2013 1 1 5 29 2013-01-01 2013-01-01 05:29:00
## 3 2013 1 1 5 40 2013-01-01 2013-01-01 05:40:00
## 4 2013 1 1 5 45 2013-01-01 2013-01-01 05:45:00
## 5 2013 1 1 6 0 2013-01-01 2013-01-01 06:00:00
## 6 2013 1 1 5 58 2013-01-01 2013-01-01 05:58:00
## 7 2013 1 1 6 0 2013-01-01 2013-01-01 06:00:00
## 8 2013 1 1 6 0 2013-01-01 2013-01-01 06:00:00
## 9 2013 1 1 6 0 2013-01-01 2013-01-01 06:00:00
## 10 2013 1 1 6 0 2013-01-01 2013-01-01 06:00:00
## # ℹ 336,766 more rows
Unir el año, mes, día, hora que estén en diferentes columnas en uno
vuelos %>%
dplyr::select(anio, mes, dia, hora, minuto) %>%
mutate(salida2 = make_date(anio, mes, dia))
## # A tibble: 336,776 × 6
## anio mes dia hora minuto salida2
## <int> <int> <int> <dbl> <dbl> <date>
## 1 2013 1 1 5 15 2013-01-01
## 2 2013 1 1 5 29 2013-01-01
## 3 2013 1 1 5 40 2013-01-01
## 4 2013 1 1 5 45 2013-01-01
## 5 2013 1 1 6 0 2013-01-01
## 6 2013 1 1 5 58 2013-01-01
## 7 2013 1 1 6 0 2013-01-01
## 8 2013 1 1 6 0 2013-01-01
## 9 2013 1 1 6 0 2013-01-01
## 10 2013 1 1 6 0 2013-01-01
## # ℹ 336,766 more rows
## Conversión de fechas que no son estándar
## # A tibble: 3 × 2
## Ind fechas
## <dbl> <chr>
## 1 1 1/1/30
## 2 2 1/30/01
## 3 3 1/30/09
## # A tibble: 3 × 3
## Ind fechas nueva_fecha
## <dbl> <chr> <date>
## 1 1 1/1/30 2030-01-01
## 2 2 1/30/01 2001-01-30
## 3 3 1/30/09 2009-01-30
Datos_raros$fecha2=as.Date(as.Date(format(as.Date(Datos_raros$fechas, format="%m/%d/%Y"), "19%y%m%d"), "%Y%m%d"))
Datos_raros
## # A tibble: 3 × 3
## Ind fechas fecha2
## <dbl> <chr> <date>
## 1 1 1/1/30 1930-01-01
## 2 2 1/30/01 1901-01-30
## 3 3 1/30/09 1909-01-30
24.10 %/%: integer division
vuelos |> dplyr::select(tiempo_vuelo) |>
mutate(t=tiempo_vuelo %/% 100) |> # Division
mutate(m= tiempo_vuelo %% 100) # modulus... Cambia el 100 para 1, 10, 1000... y mira cual es el resultado
## # A tibble: 336,776 × 3
## tiempo_vuelo t m
## <dbl> <dbl> <dbl>
## 1 227 2 27
## 2 227 2 27
## 3 160 1 60
## 4 183 1 83
## 5 116 1 16
## 6 150 1 50
## 7 158 1 58
## 8 53 0 53
## 9 140 1 40
## 10 138 1 38
## # ℹ 336,766 more rows
24.11 The %% operator returns the modulus (remainder) of a division operation.
- For instance, 5 %% 2 would return 1, as the remainder of 5 divided by 2 is 1.
## [1] "anio" "mes" "dia"
## [4] "horario_salida" "salida_programada" "atraso_salida"
## [7] "horario_llegada" "llegada_programada" "atraso_llegada"
## [10] "aerolinea" "vuelo" "codigo_cola"
## [13] "origen" "destino" "tiempo_vuelo"
## [16] "distancia" "hora" "minuto"
## [19] "fecha_hora"
hacer_fechahora_100 <- function(anio, mes, dia, tiempo) {
make_datetime(anio, mes, dia, tiempo %/% 100, tiempo %% 100)
}
vuelos_dt <- vuelos %>%
filter(!is.na(horario_salida), !is.na(horario_llegada)) %>%
mutate(
horario_salida = hacer_fechahora_100(anio, mes, dia, horario_salida),
horario_llegada = hacer_fechahora_100(anio, mes, dia, horario_llegada),
salida_programada = hacer_fechahora_100(anio, mes, dia, salida_programada),
llegada_programada = hacer_fechahora_100(anio, mes, dia, llegada_programada)
) %>%
dplyr::select(origen, destino, starts_with("atraso"), starts_with("horario"), ends_with("programada"), tiempo_vuelo)
head(vuelos_dt)
## # A tibble: 6 × 9
## origen destino atraso_salida atraso_llegada horario_salida
## <chr> <chr> <dbl> <dbl> <dttm>
## 1 EWR IAH 2 11 2013-01-01 05:17:00
## 2 LGA IAH 4 20 2013-01-01 05:33:00
## 3 JFK MIA 2 33 2013-01-01 05:42:00
## 4 JFK BQN -1 -18 2013-01-01 05:44:00
## 5 LGA ATL -6 -25 2013-01-01 05:54:00
## 6 EWR ORD -4 12 2013-01-01 05:54:00
## # ℹ 4 more variables: horario_llegada <dttm>, salida_programada <dttm>,
## # llegada_programada <dttm>, tiempo_vuelo <dbl>
24.11.0.1 Cuantos segundos hay en un dia?
vuelos_dt %>%
ggplot(aes(horario_salida)) +
geom_freqpoly(binwidth = 86400) # 86400 segundos = 1 día
vuelos_dt %>%
filter(horario_salida < ymd(20130102)) %>%
ggplot(aes(horario_salida)) +
geom_freqpoly(binwidth = 600) # 600 segundos = 10 minutos
Nota variables que no funciona
## [1] "2010-10-10" NA
## [1] "2010-01-01"
## [1] "2015-03-07"
## [1] "2017-06-06"
## [1] "2015-08-19" "2015-07-01"
## [1] "2014-12-30"
## [1] NA
## [1] NA NA
## [1] "Jan 1, 2010"
## [1] "2015-Mar-07"
## [1] "06-Jun-2017"
## [1] "Aug 19 (2015)" "Jul 1 (2015)"
## [1] "12/30/14"
## [1] "ene 1, 2010"
## [1] "Agosto 19 (2015)" "Julio 1 (2015)"
## [1] "2010-01-01"
## [1] "2015-03-07"
## [1] "2017-06-06"
## [1] "2015-08-19" "2015-07-01"
## [1] "2014-12-30"
## [1] NA
## [1] NA NA
- Ejercicios:
Hacer los ejercicios en la sección 16.2.4 del libro en español
24.12 Extrayendo parte de las fecha-hora
year()
month()
mday()
yday()
wday()
ceiling_date()
floor_date()
round_date()
- Ejercicios:
Hacer estos ejercicios en la sección 16.3.4 del libro en español. Entregar por MSTeams.
¿Cómo cambia la demora promedio durante el curso de un día? ¿Deberías usar horario_salida o salida_programada? ¿Por qué?
¿En qué día de la semana deberías salir si quieres minimizar las posibilidades de una demora?
Confirma nuestra hipótesis de que las salidas programadas en los minutos 20-30 y 50-60 están casuadas por los vuelos programados que salen más temprano. Pista: crea una variable binaria que te diga si un vuelo tuvo o no demora.
24.14 duraciones
# ¿Qué edad tiene Charles Darwin? fecha de naciemiento February 12, 1809
edad_h <- today() - ymd("1809-02-12")
edad_h <- today() - ymd(18090212)
edad_h
## Time difference of 78796 days
## [1] "6807974400s (~215.73 years)"
Otras funciones de duración
## [1] "15s"
## [1] "600s (~10 minutes)"
## [1] "43200s (~12 hours)" "86400s (~1 days)"
## [1] "0s" "86400s (~1 days)" "172800s (~2 days)"
## [4] "259200s (~3 days)" "345600s (~4 days)" "432000s (~5 days)"
## [1] "1814400s (~3 weeks)"
## [1] "31557600s (~1 years)"
24.15 Puede agregar periodos de tiempo
## [1] "63115200s (~2 years)"
## [1] "38869200s (~1.23 years)"
## [1] "2024-11-06"
## [1] "2023-11-07 18:00:00 UTC"
24.16 períodos
## [1] "2016-03-12 13:00:00 EST"
## [1] "2016-03-13 14:00:00 EDT"
## [1] "15S"
## [1] "10M 0S"
## [1] "12H 0M 0S" "24H 0M 0S"
## [1] "7d 0H 0M 0S"
## [1] "1m 0d 0H 0M 0S" "2m 0d 0H 0M 0S" "3m 0d 0H 0M 0S" "4m 0d 0H 0M 0S"
## [5] "5m 0d 0H 0M 0S" "6m 0d 0H 0M 0S"
#> [1] "1m 0d 0H 0M 0S" "2m 0d 0H 0M 0S" "3m 0d 0H 0M 0S" "4m 0d 0H 0M 0S"
#> [5] "5m 0d 0H 0M 0S" "6m 0d 0H 0M 0S"
weeks(3)
## [1] "21d 0H 0M 0S"
## [1] "1y 0m 0d 0H 0M 0S"
## [1] "60m 10d 0H 0M 0S"
## [1] "50d 25H 2M 0S"
## [1] "2016-12-31 06:00:00 UTC"
## [1] "2017-01-01"
## [1] "2016-03-13 14:00:00 EDT"
## [1] "2016-03-13 13:00:00 EDT"
## [1] "60m 10d 0H 0M 0S"
## [1] "50d 25H 2M 0S"
- intervalos
24.20 Time zones
- Sys.timezone()
- head(OlsonNames())
- tz= “”
- Ejercicios:
Seleccionar 3 archivos de los vuelos que salen o llegan a PR, (el codigo del aeropuerto es “SJU”) de la base de datos de https://www.transtats.bts.gov/DL_SelectFields.asp?Table_ID=236 Pueden ser el mismo mes en 3 diferente años o 3 diferentes mese en el mismo año.
Repite la mayoría de los análisis enseñado arriba (como practica).
Evaluar el tiempo de retrazo de los vuelos que salen de SJU en cada periodo seleccionado, y haz una gráfica para visualizar el patrón
Cual es el día preferible para no tener retraso
Cual es la mejor hora de salida para no tener retraso
Compara por lo menos 3 diferentes lineas saliendo de SJU y el periodo de retrazo.