Capítulo 8 Fechas

  • [X] Variables numéricas (individuales)
  • [X] Variables de caracteres
  • [X] Variables lógicas
  • [X] Variables de tipo fecha

Dado que el objetivo final es trabajar con datos, vamos a ver un tipo de datos muy especial: los datos de tipo fecha. Una fecha podríamos que no tiene nada de especial ya que una simple cadena de texto "2021-04-21". Sin embargo, representa un instante en el tiempo, que deberíamos poder operar como tal. ¿Qué sucedería si sumamos un 1 (un día) a una fecha definida como una cadena de texto?

# Cadena de texto
fecha_char <- "2021-04-21"
class(fecha_char)
## [1] "character"
fecha_char + 1
## Error in fecha_char + 1: argumento no-numérico para operador binario

Como ves, da error, ya que a un texto no le podemos sumar un número (no distingue entre dicha cadena de texto y, por ejemplo, "oso panda"). Por suerte contamos con el paquete lubridate, con diferentes funcionalidades para trabajar con fechas. Empecemos con la función as_date(), que nos convierte una cadena de texto en un dato de tipo fecha.

# install.packages("lubridate")
library(lubridate)

Fíjate en la diferencia.

# Fecha, mostrada como un texto pero guardada internamente como un número
fecha_date <- as_date(fecha_char)
class(fecha_date)
## [1] "Date"
fecha_date + 1 # día siguiente
## [1] "2021-04-22"
fecha_date - 3 # 3 días antes
## [1] "2021-04-18"

En el momento en que convertimos la cadena de texto a fecha, aunque se visualice como un texto, internamente es un número, por lo que podemos restar fechas (días entre ambas), podemos sumar números a fechas (fecha días después), etc. Como ya hemos dicho, las fechas y momentos temporales no serán meras cadenas de caracteres sino que tienen clases especiales asociadas. Las fechas serán guardadas internamente como el número de días transcurridos desde el 1 de enero de 1970, y las horas como número de segundos desde el 1 de enero de 1970 (para la clase POSIXct) o una lista de segundos, minutos y horas (para la clase POSIXlt).

 

La función as_date() tiene un argumento opcional, el formato en la que le estamos la fecha, que por defecto será "yyyy-mm-dd" (año en 4 cifras, guión, mes en dos cifras, guión, día en dos cifras. Si introducimos otro tipo de formato de fecha, debemos especificárselo en un segundo argumento format = ..., para R sepa el formato de fecha que le estamos pasando

as_date("10-03-2020", format = "%d-%m-%Y") # con día-mes-año (4 cifras)
## [1] "2020-03-10"
as_date("10-03-20", format = "%d-%m-%y")  # con día-mes-año (2 cifras)
## [1] "2020-03-10"
as_date("03-10-2020", format = "%m-%d-%Y") # con mes-día-año (4 cifras)
## [1] "2020-03-10"
as_date("Octubre 21, 1995 21:24", format = "%B %d, %Y %H:%M") # fecha escrita
## [1] NA

 

ERROR: sin pasar a fecha no se puede operar

Si tenemos una fecha como caracter, nunca podremos hacer operaciones (por ejemplo, restarle una unidad temporal, en este caso un día).

"2021-03-10" - 1 # error
## Error in "2021-03-10" - 1: argumento no-numérico para operador binario

Fíjate la diferencia cuando lo convertimos en fecha

fecha <- as_date("2021-03-10") - 1 # día previo
fecha
## [1] "2021-03-09"

 

8.1 Funciones de lubridate

No solo podemos convertir la fecha con as_date(), indicándole el formato. Para facilitar conversiones de formatos habituales, el paquete lubridate tiene a nuestra disposición diferentes funciones preparadas para directamente convertir fechas en distintos formatos, como la función ymd_hms() o ydm_hms()

ymd_hms("2017-11-28 14:02:00") # convertir a fecha una cadena año-mes-día + hora
## [1] "2017-11-28 14:02:00 UTC"
ydm_hms("2017-22-12 10:00:00") # convertir a fecha una cadena año-día-mes + hora
## [1] "2017-12-22 10:00:00 UTC"

De la misma manera tenemos la función dmy_hms()

dmy_hms("1 Jan 2017 23:59:59") # convertir a fecha una cadena textual de fecha + hora
## [1] "2017-01-01 23:59:59 UTC"

También podemos hacerlo de forma muy simplifica con mdy() y ymd()

mdy("July 4th, 2000") # convertir a fecha una cadena textual de fecha
## [1] "2000-07-04"
ymd(20170131)
## [1] "2017-01-31"

 

Otra de las funcionalidades que nos proporciona dicho paquetees obtener automáticamente la fecha de hoy, haciendo uso de la función today()

hoy <- today()
class(hoy) # de clase fecha
## [1] "Date"
hoy + 7 # dentro de una semana
## [1] "2022-09-22"

También podemos obtener el «hoy y ahora» con la función now(), obteniendo no solo la fecha sino la hora.

now()
## [1] "2022-09-15 17:49:02 CEST"

 

También tenemos disponibles en dicho paquete funciones para extraer facilmente algunas variables temporales como el día de la semana, el mes o el cuatrimestre, con las funciones year(), months(), day(), hour(), week(), etc.

fecha <- now()
year(fecha)
## [1] 2022
month(fecha)
## [1] 9
day(fecha)
## [1] 15
hour(fecha)
## [1] 17
minute(fecha)
## [1] 49
second(fecha)
## [1] 2.252185
week(fecha) # Número de semana (del año)
## [1] 37

También disponemos de la función wday(), que nos devuelve el día de la semana en el que estamos (por defecto, la semana empieza el domingo, pero podemos cambiarlo con el argumento opcional week_start = ...)

wday(fecha)
## [1] 5
wday(fecha, week_start = 1) # Día de la semana (empezando por el lunes)
## [1] 4

Además si usamos otro argumento opcional label = TRUE (por defecto está en FALSE), nos convertirá dichos días de la semana en los nombres (en lugar de números)

wday(fecha, week_start = 1, label = TRUE)
## [1] Thu
## Levels: Mon < Tue < Wed < Thu < Fri < Sat < Sun

 

Las funciones de month(), year(), day(), etc, pueden ser usadas tanto para extraer el valor como para cambiarlo, asignándole uno distinto

# Mantenemos la misma fecha que la actual pero solo cambiando el año
year(fecha) <- 1891

 

Al igual que podemos realizar operaciones aritméticas sencillas con las fechas, también podemos realizar comparaciones, por ejemplo, si el día actual es menor o mayor que otra fecha dada.

fecha_actual <- now()
fecha_actual > ymd(20170131) # Actual vs 2017-01-31
## [1] TRUE
fecha_actual > ymd(21000131) # Actual vs 2100-01-31
## [1] FALSE

 

Con la función leap_year() podremos saber si la fecha corresponde a un año bisiesto

leap_year(as_date(ymd(20190131)))
## [1] FALSE
leap_year(as_date(ymd(20160131)))
## [1] TRUE

También podemos hacer uso de diferentes funciones para añadir intervalos de tiempo a una fecha dada (que no sean solo días).

fecha <- now()
fecha + weeks(0:3)
## [1] "2022-09-15 17:49:02 CEST" "2022-09-22 17:49:02 CEST"
## [3] "2022-09-29 17:49:02 CEST" "2022-10-06 17:49:02 CEST"
fecha + seconds(0:3)
## [1] "2022-09-15 17:49:02 CEST" "2022-09-15 17:49:03 CEST"
## [3] "2022-09-15 17:49:04 CEST" "2022-09-15 17:49:05 CEST"

8.2 Consejos

CONSEJOS

 

Recuperar un comando y autocompletar

Si haces click con el ratón en la consola y pulsas la flecha «arriba» del teclado, te irá apareciendo todo el historial de órdenes ejecutadas. Es una manera de ahorrar tiempo para ejecutar órdenes similares a las ya ejecutadas. Si empiezas a escribir el nombre de una variable pero no te acuerdas exactamente de su nombre, pulsando tabulador te autocompletará solo.

 

Convertir tipos de datos

A veces la lectura de variables numéricas de nuestros archivos puede hacer que un número, por ejemplo 1, sea leído como la cadena de texto "1", con la que no podemos operar como un número. Las funciones as.numeric(), as.character() y as.logical() nos permiten convertir una variable en tipo numérico, caracter o lógico, respectivamente.

"1" + 1
## Error in "1" + 1: argumento no-numérico para operador binario
as.numeric("1") + 1
## [1] 2
## [1] "1"
as.logical(c(0, 1))
## [1] FALSE  TRUE

 

8.3 📝 Ejercicios

(haz click en las flechas para ver soluciones)

📝Ejercicio 1: obten la fecha de hoy, define la fecha de tu cumpleaños, y calcula la diferencia de días.

  • Solución:
# Hoy
hoy <- today()

# Cumple (diferentes formatos de entrada)
cumple <- as_date("1989-09-10") # por defecto
cumple <- as_date("10-09-1989", format = "%d-%m-%Y")

# Diferencia
hoy - cumple
## Time difference of 12058 days

 

📝Ejercicio 2: define la fecha de tu cumpleaños y determina si fue año bisiesto. Súmale 1-2-3-4-5 semanas.

  • Solución:
cumple <- as_date("1989-09-10") # por defecto

# Bisiesto
leap_year(cumple)
## [1] FALSE
# Sumamos semanaes
cumple + weeks(1:5)
## [1] "1989-09-17" "1989-09-24" "1989-10-01" "1989-10-08" "1989-10-15"

 

📝Ejercicio 3: extrae el mes, año y día de la semana de tu cumpleaños

  • Solución:
# Mes
month(cumple)
## [1] 9
# Año 
year(cumple)
## [1] 1989
# wday
wday(cumple, week_start = 1)
## [1] 7
wday(cumple, week_start = 1, label = TRUE)
## [1] Sun
## Levels: Mon < Tue < Wed < Thu < Fri < Sat < Sun

 

📝Ejercicio 4: calcula los días que han pasado desde la fecha de tu nacimiento

  • Solución:
seconds(today() - cumple)
## [1] "12058S"