Vamos a explorar el paquete Lubridate para R, creado por Garrett Grolemund y Hadley Wickham. Según los autores del paquete, “el lubridate tiene una sintaxis consistente y memorable, que hace que trabajar con las fechas sea divertido en lugar de frustrante”. Sin este paquete, manipular las fechas en R es muy complejo.
Existen diferentes representaciones de fecha y hora, para ver nuestra configuración regional usamos la siguiente función:
Sys.getlocale("LC_TIME")
## [1] "Spanish_Mexico.1252"
El paquete lubridate contiene muchas funciones útiles y en este trabajo se cubirrán las principales, por lo que si se requiere más información, es necesario teclear help (package = lubridate) en la consola para obtener una descripción general del paquete, incluyendo una lista de funciones disponibles.
La función today () devuelve la fecha de hoy. Permite almacenar el resultado en una nueva variable llamada this_day.
library(lubridate)
##
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
##
## date
this_day <- today()
this_day
## [1] "2017-06-05"
Hay tres componentes de fecha que en orden son año, mes y día. Podemos extraer cualquiera de estos componentes utilizando la función year (), month (), o day (), respectivamente. Los probaremos usando la fecha de hoy:
y <- year(this_day)
m <- month(this_day)
d <-day(this_day)
rbind(y,m,d)
## [,1]
## y 2017
## m 6
## d 5
También podemos obtener el día de la semana desde this_day usando la función wday () que se muestra representado con un número, de tal manera que 1 = Domingo, 2 = Lunes, 3 = Martes, etc. De la misma manera podemos extraer el día del mes y día del año.
w <- wday(this_day)
m <- mday(this_day)
y <- yday(this_day)
rbind(w,m,y)
## [,1]
## w 2
## m 5
## y 156
Podemos añadir un segundo argumento, label = TRUE, para mostrar el nombre del día de la semana (representado como un factor ordenado).
wday(this_day, label = TRUE)
## [1] Mon
## Levels: Sun < Mon < Tues < Wed < Thurs < Fri < Sat
Además de manejar las fechas, lubridate es ideal para trabajar con combinaciones de fecha y hora. La función now () devuelve la fecha y hora que representa este momento exacto en el tiempo. Almacenamos el resultado en una variable llamada this_moment.
this_moment <- now()
this_moment
## [1] "2017-06-05 10:34:41 CDT"
Al igual que con las fechas, podemos extraer el año, mes, día o día de la semana. Sin embargo, también podemos usar hour (), minute () y second () para extraer información específica del tiempo.
hr <- hour(this_moment)
minu <- minute(this_moment)
sec <- second(this_moment)
rbind(hr,minu,sec)
## [,1]
## hr 10.00000
## minu 34.00000
## sec 41.58855
Today () y now () proporcionan información de fecha-hora con formato corecto, sin embargo, cuando se trabaja con fechas y horas de una base de datos común y corriente, esto no siempre será así, al contrario, serán raros los caso en los que el formato en bases de datos sea el adecuado.
Afortunadamente, el paquete lubridate ofrece una variedad de funciones para analizar la fecha y hora. Estas funciones toman la forma de ymd (),dmy (), hms (), ymd_hms (), etc., donde cada letra en el nombre de la función representa la ubicación de años (y), meses (m), días (D), horas (h), minutos (m) y / o segundos (s) en la fecha de lectura.
Para ver cómo funcionan estas funciones, pongamos ymd (“1989-05-17”). Debemos poner la fecha entre comillas.
my_date <- ymd("1989-05-17")
my_date
## [1] "1989-05-17"
Parece casi lo mismo, excepto por la adición de una zona horaria, de la cual se hablará más adelante. Hay además otro cambio importante que ocurre cuando el lubridate analiza una fecha.
class(my_date)
## [1] "Date"
De esta forma, ymd () tomó una cadena de caracteres como entrada y devolvió un objeto de clase POSIXct. POSIXct, es una forma en que R almacena la información de fecha y hora internamente.
“1989-05-17” es un formato bastante estándar, pero lubridate es lo suficientemente inteligente como para averiguar muchos formatos diferentes de fecha y hora. Usamos ymd () para analizar “1989 17 de mayo”.
ymd("1989 May 17")
## [1] "1989-05-17"
A pesar de tener formato diferente, las dos últimas fechas tenían el año primero y luego el mes y al final el día. Por lo tanto, usamos ymd () para analizarlos. ¿CUál será la función apropiada para analizar el formato “12 de marzo de 1975”?
mdy("March 12, 1975")
## [1] "1975-12-19"
Incluso podemos poner algo raro y lubridate sabrá qué hacer en la mayoría de los casos. Vamos a analizar 25081985, que se supone que representa el día 25 de agosto de 1985. Es importante tener en cuenta que en realidad estamos analizando un valor numérico aquí no una cadena de caracteres por lo tanto no lleva comillas.
dmy(25081985)
## [1] "1985-08-25"
Sin embargo siempre hay qué ser cuidadosos pues, como todo componente tecnológico, este paquete tiene sus limitaciones. intentemos ymd (“192012”) para ver qué pasa cuando le damos algo más ambiguo. Estamos usnaod comillas de nuevo, sólo para ser coherente con la forma en que la mayoría de las fechas se representan, es decir, como cadenas de caracteres.
ymd("192012")
## Warning: All formats failed to parse. No formats found.
## [1] NA
Recibimos un mensaje de advertencia porque no estaba claro qué fecha queríamos. En caso de duda, lo mejor es ser más explícito. Vamos a repetir el mismo comando, pero agregue dos guiones O dos barras a “192012” para que quede claro que queremos el 2 de enero de 1920.
# or ymd("1920-1-2")
ymd("1920/1/2")
## [1] "1920-01-02"
Podemos analizar además fechas con un horario específico. Permite crear un objeto de fecha y hora denominado dt1 y analizarlo con ymd_hms ().
dt1 <- '2014-08-23 17:23:02'
ymd_hms(dt1)
## [1] "2014-08-23 17:23:02 UTC"
¿Qué pasa si tenemos horario, pero no hay fecha? En ese caso se utiliza la función apropiada de lubridate para ese tipo de datos “03:22:14” (hh: mm: ss).
hms("03:22:14")
## [1] "3H 22M 14S"
Lubridate también es capaz de manejar vectores de fechas, lo cual es particularmente útil cuando se necesita analizar una columna completa de datos.
dt2 <- c('2014-05-14', '2014-09-22', '2014-07-11')
ymd(dt2)
## [1] "2014-05-14" "2014-09-22" "2014-07-11"
La función update () nos permite actualizar uno o más componentes de datos con fecha y hora. Por ejemplo, digamos que la hora actual es 08:34:55 (hh: mm: ss). Permite actualizar la función this_moment a la nueva hora usando update (this_moment, hours = 8, minutes = 34, seconds = 55).
update(this_moment, hours = 8, minutes = 34, seconds = 55)
## [1] "2017-06-05 08:34:55 CDT"
Vamos a actualizar () this_moment, para que contenga la nueva hora.
update(this_moment, hours = 8, minutes = 34, seconds = 55)
## [1] "2017-06-05 08:34:55 CDT"
Hagamos un ejercicio: digamos que estamos en Nueva York y que estamos planeando visitar a un amigo en Hong Kong. Extraviamos el itinerario, pero sabemos que el vuelo sale de Nueva York a las 17:34 (5:34 pm) pasado mañana. Sabemos también que el vuelo está programado para llegar a Hong Kong exactamente 15 horas y 50 minutos después de la salida.
Vamos a reconstruir el itinerario desde lo que recordamos, comenzando con la fecha y hora completas de la salida del avión; para hacerlo, debemos obtener la fecha actual en Nueva Yorky agregamos 2 días completos, luego ponemos la hora a 17:34.
Para encontrar la fecha actual en Nueva York, volveremos a usar la función now (). Esta vez, sin embargo, especificaremos la zona horaria que queremos: “America / New_York”. Para una lista completa de zonas horarias válidas para su uso con lubridate, consultar el siguiente enlace: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
nyc <- now("America/New_York")
nyc
## [1] "2017-06-05 11:34:42 EDT"
El vuelo es pasado mañana, así que queremos añadir dos días a la fecha atcual. Una característica muy útil de lubridate es que le permite utilizar operadores aritméticos en fechas y horas. En este caso, vamos a agregar dos días a la fecha, por lo que podemos usar la siguiente expresión: nyc + days (2)
depart <- nyc + days(2)
depart
## [1] "2017-06-07 11:34:42 EDT"
La función Depart contiene la fecha de pasado mañana. Utilizamos update () para agregar las horas correctas (17) y los minutos (34) que es el tiempo exacto de la salida del vuelo. Se reasigna el resultado a la función depart.
depart <- update(depart, hours = 17, minutes = 34)
depart
## [1] "2017-06-07 17:34:42 EDT"
Nuestro amigo quiere saber a qué hora debe recogerte en el aeropuerto de Hong Kong. Ahora que tenemos la fecha y hora exactas de la salida de Nueva York, podemos averiguar la hora exacta de su llegada a Hong Kong.
El primer paso es añadir 15 horas y 50 minutos a la hora de salida. Recordemos que nyc + days (2) agregó dos días a la hora actual en Nueva York. Utilicemos el mismo procedimiento para agregar 15 horas y 50 minutos a la fecha y hora del viaje.
arrive <- depart + hours(15) + minutes(50)
arrive
## [1] "2017-06-08 09:24:42 EDT"
La variable arrive contiene la hora de Nueva York cuando se llegue a Hong Kong. Lo que realmente queremos saber es qué hora será en Hong Kong cuando lleguemos, para que nuestro amigo sepa cuándo recogernos.
La función with_tz () devuelve una fecha-hora tal como aparecería en otra zona horaria. Utilizamos with_tz () para convertir arrive a la zona horaria “Asia / Hong_Kong”.
arrive <- with_tz(arrive, "Asia/Hong_Kong")
arrive
## [1] "2017-06-08 21:24:42 HKT"
Hemos llegado a Hong Kong. Nos hemos reunido con nuestro amigo en el aeropuerto y nos damos cuenta de que la última vez que estuvimos juntos fue en Singapur el 17 de junio de 2008. Naturalmente, le gustaría saber exactamente cuánto tiempo ha pasado. Sólo necesitamos utilizar la función apropiada de lubridate para analizar “17 de junio de 2008”. Esta vez, sin embargo, deberíamos especificar un argumento adicional, tz = “Singapur”.
last_time <- mdy("06-17-2008", tz = "Singapore")
last_time
## [1] "2008-06-17 SGT"
Podemos crear un interval () que se extiende desde last_time hasta arrive.
how_long <- interval(last_time, arrive)
how_long
## [1] 2008-06-17 SGT--2017-06-08 21:24:42 SGT
Ahora debemos usar as.period () para ver cuánto tiempo ha pasado.
as.period(how_long)
## [1] "8y 11m 22d 21H 24M 42.1159420013428S"
Aquí es donde las cosas se ponen un poco complicadas. Debido a factores como años bisiestos y el horario de verano, la duración de cualquier minuto, día, mes, semana o año es relativa a cuándo ocurre. En contraste, la longitud de un segundo es siempre la misma.
Para abordar estas complejidades, los autores de lubridate ofrecen cuatro clases de funciones relacionadas con el tiempo: instantes, intervalos, duraciones y períodos. Estos temas están más allá del alcance de este trabajo, pero se puede encontrar un recurso muy completo en la publicación de 2011 del Journal of Statistical Software, titulado “Dates and Times Made Easy with Lubridate”