9 Trabajando con Fechas
Trabajar con fechas en R requiere más atención que trabajar con otros tipos de objetos. A continuación, ofrecemos algunas herramientas y ejemplos para hacer este proceso menos doloroso. Por suerte, las fechas pueden manejarse fácilmente con la práctica y con un conjunto de paquetes útiles como lubridate.
Al importar los datos en bruto, R suele interpretar las fechas como objetos de carácter, lo que significa que no pueden utilizarse para operaciones generales con fechas, como la creación de series temporales y el cálculo de intervalos de tiempo. Para hacer las cosas más difíciles, hay muchas maneras de formatear una fecha y debes ayudar a R a saber qué parte de una fecha representa qué (mes, día, hora, etc.).
Las fechas en R son su propio tipo de objeto - el tipo Date. Hay que tener en cuenta que también hay un tipo que almacena objetos con fecha y hora. Los objetos fecha-hora se denominan formalmente tipos POSIXt
, POSIXct
, o POSIXlt
(la diferencia no es importante). Estos objetos se denominan informalmente tipos datetime.
- Es importante hacer que R reconozca cuando una columna contiene fechas.
- Las fechas son un tipo de objeto y pueden ser difíciles de trabajar.
- Aquí presentamos varias formas de convertir columnas de fecha al tipo Date.
9.1 Preparación
Cargar paquetes
Este trozo de código muestra la carga de paquetes necesaria para esta página. En este manual destacamos p_load()
de pacman, que instala el paquete si es necesario y lo carga para su uso. También puedes cargar los paquetes instalados con library()
de R base. Consulta la página sobre los Fundamentos de R para obtener más información sobre los paquetes de R.
# Ccomprueba si el paquete está instalado, lo instala si es necesario y lo carga para la sesión actual.
::p_load(
pacman# paquete general para manejar y convertir fechas
lubridate, # tiene una función para "adivinar" fechas desordenadas
parsedate, # otra opción para convertir fechas en semanas, y semanas en fechas
aweek, # funciones adicionales de fecha/hora
zoo, # gestión de archivos
here, # gestión y visualización de datos
tidyverse, # importación/exportación de datos rio)
Importar datos
Importamos los datos de casos de una epidemia de ébola simulada. Si deseas descargar los datos para seguirlos paso a paso, consulta las instrucciones en la página de descarga de manuales y datos. Asumimos que el archivo está en el directorio de trabajo, por lo que no se especifican subcarpetas en esta ruta de archivo.
<- import("linelist_cleaned.xlsx") linelist
9.2 Fecha actual
Puedes obtener la fecha actual del “sistema” o la fecha-hora del sistema de tu ordenador haciendo lo siguiente con R base.
# obtener la fecha del sistema - esta es de tipo DATE (FECHA)
Sys.Date()
[1] "2024-09-18"
# obtener la hora del sistema - esta es de tipo DATETIME (FECHAHORA)
Sys.time()
[1] "2024-09-18 21:38:12 +07"
Con el paquete lubridate también se pueden devolver con today()
y now()
, respectivamente. date()
devuelve la fecha y la hora actuales con los nombres del día de la semana y del mes.
9.3 Convertir en fecha
Después de importar unos datos a R, los valores de las columnas de fecha pueden tener el aspecto de “1989/12/30”, “05/06/2014” o “13 Ene 2020”. En estos casos, es probable que R siga tratando estos valores como valores de carácter. Hay que decirle a R que estos valores son fechas… y cuál es el formato de la fecha (qué parte es Día, cuál es Mes, cuál es Año, etc).
Una vez dicho esto, R convierte estos valores al tipo Date. En segundo plano, R almacenará las fechas como números (el número de días desde su fecha “origen” 1 Ene 1970). No interactuarás con el número de la fecha a menudo, pero esto permite a R tratar las fechas como variables continuas y permitir operaciones especiales como el cálculo de la distancia entre las fechas.
Por defecto, los valores del tipo Date en R se muestran como AAAA-MM-DD. Más adelante en esta sección discutiremos cómo cambiar la visualización de los valores de fecha.
A continuación presentamos dos enfoques para convertir una columna de valores de carácter al tipo Date.
CONSEJO:: Puedes comprobar el tipo actual de una columna con la función class()
de R base, como class(linelist$date_onset)
.
R base
as.Date()
es la función estándar de R base para convertir un objeto o una columna en el tipo Date (nótese la “D” en mayúscula).
El uso de as.Date()
requiere que:
- Se especifique el formato existente de la fecha de carácter en bruto o la fecha de origen si se suministran las fechas como números (véase la sección sobre las fechas de Excel)
- Si se utiliza en una columna de caracteres, todos los valores de fecha deben tener el mismo formato exacto (si no es el caso, pruebe con
parse_date()
del paquete parsedate)
En primer lugar, comprueba el tipo de la columna con class()
de R base . Si no estás seguro o estás confundido sobre el tipo de datos (por ejemplo, ve “POSIXct”, etc.) puede ser más fácil convertir primero la columna al tipo Character con as.character()
, y luego convertirla al tipo Date.
En segundo lugar, dentro de la función as.Date()
, utiliza el argumento format =
para indicar a R el formato actual de los componentes de la fecha con caracteres - qué caracteres se refieren al mes, al día y al año, y cómo están separados. Si sus valores ya están en uno de los formatos de fecha estándar de R (“AAAA-MM-DD” o “AAAA/MM/DD”) el argumento format =
no es necesario.
Para usar format =
, escribe una cadena de caracteres (entre comillas) que represente el formato actual de la fecha utilizando las abreviaturas especiales “strptime” que aparecen a continuación. Por ejemplo, si las fechas de caracteres están actualmente en el formato “DD/MM/AAAA”, como “24/04/1968”, entonces usarías format = "%d/%m/%Y"
para convertir los valores en fechas. Es necesario poner el formato entre comillas. ¡Y no olvides las barras o guiones!.
# Convertir a tipo fecha
<- linelist %>%
linelist mutate(date_onset = as.Date(date_of_onset, format = "%d/%m/%Y"))
La mayoría de las abreviaturas de strptime se enumeran a continuación. Puedes ver la lista completa ejecutando ?strptime
.
%d = Número del día del mes (5, 17, 28, etc.) %j = Número del día del año (día juliano 001-366) %a = Día de la semana abreviado (lunes, martes, miércoles, etc.) %A = Día de la semana completo (lunes, martes, etc.) %w = Número del día de la semana (0-6, el domingo es 0) %u = Número del día de la semana (1-7, el lunes es 1) %W = Número de la semana (00-53, el lunes es el comienzo de la semana) %U = Número de la semana (01-53, el domingo es el comienzo de la semana) %m = Número del mes (p. ej. 01, 02, 03, 04) %b = Mes abreviado (enero, febrero, etc.) %B = Mes completo (enero, febrero, etc.) %y = Año de 2 dígitos (p. ej. 89) %Y = Año de 4 dígitos (p. ej. 1989) %h = Horas (reloj de 24 horas) %m = Minutos %s = Segundos %z = Desplazamiento respecto a GMT %Z = Huso horario (carácter)
CONSEJO: El argumento format =
de as.Date()
no le dice a R el formato que quiere que tengan las fechas, sino cómo identificar las partes de la fecha tal y como son antes de ejecutar el comando.
CONSEJO: Asegúrate que en el argumento format =
se utiliza el mismo separador de partes de fechas (por ejemplo, /, -, o espacio) que está en tus fechas.
Una vez que los valores están en el tipo Fecha, R los mostrará por defecto en el formato estándar, que es AAAA-MM-DD.
lubridate
La conversión de objetos de carácter a fechas puede facilitarse utilizando el paquete lubridate. Se trata de un paquete tidyverse diseñado para hacer que el trabajo con fechas y horas sea más sencillo y consistente que en R base. Por estas razones, el paquete lubridate se considera a menudo el estándar de oro para las fechas y la hora, y se recomienda siempre que se trabaje con ellas.
El paquete lubridate proporciona varias funciones de ayuda diferentes diseñadas para convertir objetos de caracteres en fechas de una manera intuitiva y más indulgente que especificando el formato en as.Date()
. Estas funciones son específicas para el formato de fecha aproximado, pero permiten una variedad de separadores, y sinónimos para las fechas (por ejemplo, 01 vs Jan vs Enero) - se denominan según las abreviaturas de los formatos de fecha.
# instalar/cargar lubridate
::p_load(lubridate) pacman
La flexibilidad de la función ymd()
convierte de forma flexible los valores de fecha suministrados como año, luego mes y luego día.
# leer la fecha en formato año-mes-día
ymd("2020-10-11")
[1] "2020-10-11"
ymd("20201011")
[1] "2020-10-11"
La función mdy()
convierte de forma flexible los valores de fecha suministrados como mes, luego día y luego año.
# leer la fecha en formato mes-día-año
mdy("10/11/2020")
[1] "2020-10-11"
mdy("Oct 11 20")
[1] "2020-10-11"
La función dmy()
convierte de forma flexible los valores de fecha suministrados como día, luego mes y luego año.
# leer la fecha en formato día-mes-año
dmy("11 10 2020")
[1] "2020-10-11"
dmy("11 October 2020")
[1] "2020-10-11"
Si se utilizan pipes, la conversión de una columna de caracteres a fechas con lubridate podría tener este aspecto:
<- linelist %>%
linelist mutate(date_onset = lubridate::dmy(date_onset))
Una vez completado, puedes ejecutar class()
para verificar el tipo de la columna
# Comprueba el tio de columna
class(linelist$date_onset)
Una vez que los valores están en el tipo Fecha, R los mostrará por defecto en el formato estándar, que es AAAA-MM-DD.
Ten en cuenta que las funciones anteriores funcionan mejor con años de 4 dígitos. Los años de 2 dígitos pueden producir resultados inesperados, ya que lubridate intenta adivinar el siglo.
Para convertir un año de 2 dígitos en un año de 4 dígitos (todos en el mismo siglo) puedes convertirlo a tipo carácter y luego combinar los dígitos existentes con un prefijo usando str_glue()
del paquete stringr. Ver Caracteres y cadenas. A continuación, convierte a fecha.
<- c("15", "15", "16", "17")
two_digit_years str_glue("20{two_digit_years}")
2015
2015
2016
2017
Combinar columnas
Puedes utilizar las funciones de lubridate make_date()
y make_datetime()
para combinar varias columnas numéricas en una columna de fecha. Por ejemplo, si tiene columnas numéricas onset_day
, onset_month
y onset_year
en el dataframe linelist
:
<- linelist %>%
linelist mutate(onset_date = make_date(year = onset_year, month = onset_month, day = onset_day))
9.4 Fechas en Excel
En el fondo, la mayoría de los programas informáticos almacenan las fechas como números. R almacena las fechas desde un origen del 1 de enero de 1970. Así, si ejecutas as.numeric(as.Date("1970-01-01"))
obtendrás 0
.
Microsoft Excel almacena las fechas con un origen dependiendo del sistema operativo, del 30 de diciembre de 1899 (Windows) o del 1 de enero de 1904 (Mac). Consulta esta guía de Microsoft para obtener más información.
Las fechas de Excel suelen importarse a R como estos valores numéricos en lugar de como caracteres. Si los datos que has importado de Excel muestran las fechas como números o caracteres como “41369”… utiliza as.Date()
(o la función as_date()
de lubridate) para convertirlas, pero en lugar de suministrar un “formato” como el anterior, suministra la fecha de origen de Excel al argumento origin =
.
Esto no funcionará si la fecha de Excel se almacena en R como de tipo carácter, ¡así que asegúrate de que el número es de tipo numérico!.
NOTA: Debes proporcionar la fecha de origen en el formato de fecha por defecto de R (“AAAA-MM-DD”).
# Un ejemplo de proporcionar la "fecha de origen" de Excel al convertir fechas numéricas de Excel
<- data %>%
data_cleaned mutate(date_onset = as.numeric(date_onset)) %>% # asegura que la clase es numérica
mutate(date_onset = as.Date(date_onset, origin = "1899-12-30")) # convierte a fecha usando el origen de Excel
9.5 Fechas desordenadas
La función parse_date()
del paquete parsedate intenta leer una columna de fecha “desordenada” que contiene fechas en muchos formatos diferentes y convertir las fechas a un formato estándar. Puedes leer más en línea sobre guess_dates()
.
Por ejemplo parse_date()
vería un vector de las siguientes fechas de caracteres “03 Ene 2018”, “07/03/1982”, y “08/20/85” y las convertiría al tipo Date como 2018-01-03
, 1982-03-07
, y 1985-08-20
.
::parse_date(c("03 Jany 2018",
parsedate"07/03/1982",
"08/20/85"))
[1] "2018-01-03 UTC" "1982-07-03 UTC" "1985-08-20 UTC"
# Un ejemplo usando guess_dates en la columna date_onset
<- linelist %>% # el conjunto de datos se llama linelist
linelist mutate(
date_onset = parsedate::parse_date(date_onset)) # parse_date() del paquete "parsedate"
9.6 Trabajar con el tipo fecha-hora
Como se mencionó anteriormente, R también soporta un tipo datetime
- una columna que contiene información de fecha y hora. Al igual que con el tipo Date, a menudo es necesario convertirlas de objetos character
a objetos datetime
.
Convertir fechas con horas
Un objeto datetime
estándar se formatea con la fecha en primer lugar, seguida de un componente de tiempo - por ejemplo, 01 Ene 2020, 16:30. Al igual que con las fechas, hay muchas maneras de formatearlas, y hay numerosos niveles de precisión (horas, minutos, segundos) que se pueden suministrar.
Por suerte, también existen funciones de ayuda de lubridate para ayudar a convertir estas cadenas en objetos datetime
. Estas funciones son extensiones de las funciones de ayuda a la fecha, con _h
(sólo se suministran las horas), _hm
(se suministran las horas y los minutos), o _hms
(se suministran las horas, los minutos y los segundos) añadidas al final (por ejemplo, dmy_hms()
). Se pueden utilizar como se indica:
Convertir datetime
con sólo horas a objeto datetime
ymd_h("2020-01-01 16hrs")
[1] "2020-01-01 16:00:00 UTC"
ymd_h("2020-01-01 4PM")
[1] "2020-01-01 16:00:00 UTC"
Convertir datetime
con horas y minutos a objeto datetime
dmy_hm("01 January 2020 16:20")
[1] "2020-01-01 16:20:00 UTC"
Convertir datetime
con horas, minutos y segundos a objeto datetime
mdy_hms("01 January 2020, 16:20:40")
[1] "2020-01-20 16:20:40 UTC"
Puedes indicar la zona horaria, pero se ignora. Consulta la sección más adelante en esta página sobre las zonas horarias.
mdy_hms("01 January 2020, 16:20:40 PST")
[1] "2020-01-20 16:20:40 UTC"
Cuando se trabaja con un dataframe, las columnas de fecha y hora pueden combinarse para crear una columna de fecha y hora utilizando str_glue()
del paquete stringr y una función apropiada de lubridate. Consulta la página sobre Caracteres y cadenas para obtener detalles sobre stringr.
En este ejemplo, el dataframe linelist
tiene una columna con formato “horas:minutos”. Para convertirla en una fecha, hay que seguir algunos pasos:
- Crea una columna de tiempo de admisión “limpia” con los valores faltantes rellenados con la mediana de la columna. Hacemos esto porque lubridate no opera con valores faltantes. Combínala con la columna
date_hospitalisation
y utiliza la funciónymd_hm()
para convertirla.
# paquetes
::p_load(tidyverse, lubridate, stringr)
pacman
# time_admission es una columna en horas:minutos
<- linelist %>%
linelist
## cuando no se da la hora de admisión, asigna la mediana del tiempo de admisión
mutate(
time_admission_clean = ifelse(
is.na(time_admission), # si falta el hora
median(time_admission), # asignar la mediana
# si no falta la hora mantenerla
time_admission %>%
)
# utilizar str_glue() para combinar las columnas de fecha y hora para crear una columna de caracteres
# y luego usar ymd_hm() para convertirla en fecha-hora
mutate(
date_time_of_admission = str_glue("{date_hospitalisation} {time_admission_clean}") %>%
ymd_hm()
)
Convertir sólo horas
Si tus datos contienen sólo un carácter de tiempo (horas y minutos), puedes convertirlos y manipularlos como tiempos utilizando strptime()
desde R base. Por ejemplo, para obtener la diferencia entre dos de estos horas:
# hora cruda de tipo carácter
<- "13:45"
time1 <- "15:20"
time2
# Horas convertidas a una clase fecha
<- strptime(time1, format = "%H:%M")
time1_clean <- strptime(time2, format = "%H:%M")
time2_clean
# La diferencia es de tipo "difftime" por defecto, aquí convertida a horas numéricas
as.numeric(time2_clean - time1_clean) # diferencia en horas
[1] 1.583333
Sin embargo, ten en cuenta que si no se proporciona un valor de fecha, se asume que la fecha es hoy. Para combinar una cadena de fecha y una cadena de hora, observa cómo se usa stringr en la sección anterior. Puedes leer más sobre strptime()
aquí.
Para convertir números de un solo dígito a dos dígitos (por ejemplo, para “rellenar” las horas o los minutos con ceros a la izquierda para conseguir 2 dígitos), consulta la sección “Longitud de relleno” de la página Caracteres y cadenas.
Extraer fracciones de hora
Puedes extraer elementos de una hora con hour()
, minute()
, o second()
de lubridate.
He aquí un ejemplo de extracción de la hora y posterior clasificación como parte del día. Comenzamos con la columna time_admission
, que es de tipo Carácter en formato “HH:MM”. En primer lugar, se utiliza strptime()
como se ha descrito anteriormente para convertir los caracteres en tipo datetime
. A continuación, se extrae la hora con hour()
, devolviendo un número del 0 al 24. Por último, se crea una columna time_period
utilizando la lógica con case_when()
para clasificar las filas en Mañana/Tarde/Anochecer/Noche en función de su hora de entrada.
<- linelist %>%
linelist mutate(hour_admit = hour(strptime(time_admission, format = "%H:%M"))) %>%
mutate(time_period = case_when(
> 06 & hour_admit < 12 ~ "Morning",
hour_admit >= 12 & hour_admit < 17 ~ "Afternoon",
hour_admit >= 17 & hour_admit < 21 ~ "Evening",
hour_admit >=21 | hour_admit <= 6 ~ "Night")) hour_admit
Para saber más sobre case_when()
, consulta la página sobre Limpieza de datos y funciones básicas.
9.7 Trabajar con fechas
lubridate
también puede utilizarse para otras funciones, como la extracción de aspectos de una fecha/hora, realización de cálculos aritméticos de fechas o cálculo de intervalos de fechas
Aquí definimos una fecha que se utilizará para los ejemplos:
# crear un objeto de clase Date
<- ymd("2020-03-01") example_date
Extraer los componentes de la fecha
Puedes extraer aspectos comunes como el mes, el día, el día de la semana:
month(example_date) # número del mes
[1] 3
day(example_date) # día (número) del mes
[1] 1
wday(example_date) # número de día de la semana (1-7)
[1] 1
También puede extraer componentes de tiempo de un objeto o columna datetime
. Esto puede ser útil si quieres ver la distribución de los tiempos de admisión.
<- ymd_hm("2020-03-01 14:45")
example_datetime
hour(example_datetime) # extraer la hora
minute(example_datetime) # extraer el minuto
second(example_datetime) # extraer el segundo
Hay varias opciones para recuperar las semanas. Consulta la sección sobre semanas epidemiológicas más abajo.
Ten en cuenta que si deseas mostrar una fecha de una forma determinada (por ejemplo, “enero de 2020” o “jueves 20 de marzo” o “semana 20 de 1977”) puedes hacerlo de forma más flexible, tal y como se describe en la sección sobre Visualización de fechas.
Fecha matemática
Puedes añadir ciertos números de días o semanas utilizando su respectiva función de lubridate.
# añadir 3 días a esta fecha
+ days(3) example_date
[1] "2020-03-04"
# añade 7 semanas y resta dos días a esta fecha
+ weeks(7) - days(2) example_date
[1] "2020-04-17"
Intervalos de fechas
La diferencia entre las fechas se puede calcular mediante:
- Asegúrate que ambas fechas son del mismo tipo
- Utiliza la resta para devolver la diferencia “difftime” entre las dos fechas
- Si es necesario, convierte el resultado en tipo numéricoa para realizar los cálculos matemáticos posteriores
A continuación se calcula y muestra el intervalo entre dos fechas. Se pueden encontrar intervalos utilizando el símbolo de resta “menos” en los valores que son de tipo Fecha. Ten en cuenta, sin embargo, que el tipo del valor devuelto es “difftime”, como se muestra a continuación, y debe ser convertido a numérico.
# encontrar el intervalo entre esta fecha y el 20 de febrero de 2020
<- example_date - ymd("2020-02-20")
output # imprimir output
Time difference of 10 days
class(output)
[1] "difftime"
Para realizar operaciones posteriores sobre un “difftime”, conviértelo en numérico con as.numeric()
.
Todo esto puede unirse para trabajar con datos, por ejemplo:
::p_load(lubridate, tidyverse) # load packages
pacman
<- linelist %>%
linelist
# convertir la fecha de inicio de los objetos carácter a fecha especificando el formato dmy
mutate(date_onset = dmy(date_onset),
date_hospitalisation = dmy(date_hospitalisation)) %>%
# filtrar todos los casos sin inicio en marzo
filter(month(date_onset) == 3) %>%
# encontrar la diferencia de días entre el inicio y la hospitalización
mutate(days_onset_to_hosp = date_hospitalisation - date_of_onset)
En un contexto de dataframe, si falta alguna de las fechas anteriores, la operación fallará para esa fila. El resultado será un NA en lugar de un valor numérico. Cuando utilices esta columna para los cálculos, asegúrate de establecer el argumento na.rm
= en TRUE. Por ejemplo:
# Calcular la mediana del número de días hasta la hospitalización para todos los casos de los que se dispone de datos
median(linelist_delay$days_onset_to_hosp, na.rm = T)
9.8 Visualización de fechas
Una vez que las fechas son del tipo correcto, a menudo se desea mostrarlas de forma diferente, por ejemplo para que se muestren como “lunes 05 de enero” en lugar de “2018-01-05”. También puedes querer ajustar la visualización para agrupar las filas por los elementos de fecha mostrados, por ejemplo, para agrupar por mes-año.
format()
Ajusta la visualización de la fecha con la función format()
de R base. Esta función acepta una cadena de caracteres (entre comillas) que especifica el formato de salida deseado en las abreviaturas strptime “%” (la misma sintaxis que se utiliza en as.Date()
). A continuación se muestran las abreviaturas más comunes.
Nota: el uso de format()
convertirá los valores al tipo Character, por lo que generalmente se utiliza hacia el final de un análisis o sólo para fines de visualización. Puedes ver la lista completa ejecutando ?strptime
.
%d = Número del día del mes (5, 17, 28, etc.) %j = Número del día del año (día juliano 001-366) %a = Día de la semana abreviado (lunes, martes, miércoles, etc.) %A = Día de la semana completo (lunes, martes, etc.) %w = Número del día de la semana (0-6, el domingo es 0) %u = Número del día de la semana (1-7, el lunes es 1) %W = Número de la semana (00-53, el lunes es el comienzo de la semana) %U = Número de la semana (01-53, el domingo es el comienzo de la semana) %m = Número del mes (p. ej. 01, 02, 03, 04) %b = Mes abreviado (enero, febrero, etc.) %B = Mes completo (enero, febrero, etc.) %y = Año de 2 dígitos (p. ej. 89) %Y = Año de 4 dígitos (p. ej. 1989) %h = Horas (reloj de 24 horas) %m = Minutos %s = Segundos %z = Desplazamiento respecto a GMT %Z = Huso horario (carácter)
Un ejemplo de formato de la fecha de hoy:
# # fecha de hoy, con formato
format(Sys.Date(), format = "%d %B %Y")
[1] "18 September 2024"
# forma sencilla de obtener la fecha y hora completas (formato por defecto)
date()
[1] "Wed Sep 18 21:38:13 2024"
# formato combinado de fecha, hora y zona horaria usando la función str_glue()
str_glue("{format(Sys.Date(), format = '%A, %B %d %Y, %z %Z, ')}{format(Sys.time(), format = '%H:%M:%S')}")
Wednesday, September 18 2024, +0000 UTC, 21:38:13
# Utilizar format para mostrar las semanas
format(Sys.Date(), "%Y Week %W")
[1] "2024 Week 38"
Ten en cuenta que si utilizas str_glue()
, dentro de las comillas dobles ” sólo debes utilizar comillas simples (como arriba).
Mes-Año
Para convertir una columna de fecha al formato mes-año, te sugerimos que utilice la función as.yearmon()
del paquete zoo. Esto convierte la fecha al tipo “yearmon” y mantiene el orden correcto. Por el contrario, usar format(columna, "%Y %B")
convertirá al tipo Carácter y ordenará los valores alfabéticamente (incorrectamente).
A continuación, se crea una nueva columna yearmonth
a partir de la columna date_onset
, utilizando la función as.yearmon()`. La ordenación por defecto (correcta) de los valores resultantes se muestra en la tabla.
# crear una columna nueva
<- linelist %>%
test_zoo mutate(yearmonth = zoo::as.yearmon(date_onset))
# imprimir tabla
table(test_zoo$yearmon)
Apr 2014 May 2014 Jun 2014 Jul 2014 Aug 2014 Sep 2014 Oct 2014 Nov 2014
7 64 100 226 528 1070 1112 763
Dec 2014 Jan 2015 Feb 2015 Mar 2015 Apr 2015
562 431 306 277 186
Por el contrario, se puede ver cómo sólo utilizando format()
se consigue el formato de visualización deseado, pero no el orden correcto.
# crear una columna nueva
<- linelist %>%
test_format mutate(yearmonth = format(date_onset, "%b %Y"))
# imprimir tabla
table(test_format$yearmon)
Apr 2014 Apr 2015 Aug 2014 Dec 2014 Feb 2015 Jan 2015 Jul 2014 Jun 2014
7 186 528 562 306 431 226 100
Mar 2015 May 2014 Nov 2014 Oct 2014 Sep 2014
277 64 763 1112 1070
Nota: si estás trabajando con ggplot()
y quieres ajustar sólo cómo se muestran las fechas, puede ser suficiente proporcionar un formato strptime al argumento date_labels =
en scale_x_date()
- puedes utilizar "%b %Y"
o "%Y %b"
. Consulta la página de consejos de ggplot.
zoo también ofrece la función as.yearqtr()
, y puedes usar scale_x_yearmon()
cuando uses ggplot()
.
9.9 Semanas epidemiológicas
lubridate
Consulta la página sobre Agrupar datos para ver ejemplos más extensos de agrupación de datos por fecha. A continuación describimos brevemente la agrupación de datos por semanas.
Generalmente recomendamos utilizar la función floor_date()
de lubridate, con el argumento unit = "week"
. Esto redondea la fecha hacia abajo al “inicio” de la semana, como se define por el argumento week_start =
. El inicio de la semana por defecto es el 1 (para los lunes), pero se puede especificar cualquier día de la semana como inicio (por ejemplo, el 7 para los domingos). floor_date()
es versátil y se puede utilizar para redondear hacia abajo a otras unidades de tiempo estableciendo unit =
“second”, “minute”, “hour”, “day”, “month”, o “year”.
El valor devuelto es la fecha de inicio de la semana, en tipo Date. El tipo Date
es útil a la hora de representar los datos, ya que serán fácilmente reconocidos y ordenados correctamente por ggplot()
.
Si sólo tienes interés en ajustar las fechas para que se muestren por semanas en un gráfico, consulta la sección de esta página sobre Visualización de fechas. Por ejemplo, al representar una epicurva puedes formatear la visualización de la fecha proporcionando la nomenclatura strptime “%” deseada. Por ejemplo, utiliza “%Y-%W” o “%Y-%U” para devolver el año y el número de semana (dado el comienzo de la semana del lunes o del domingo, respectivamente).
Recuentos semanales
Consulta la página sobre Agrupar datos para obtener una explicación detallada de la agrupación de datos con count()
, group_by()
, and summarise()
. A continuación se muestra un breve ejemplo.
Crear una nueva columna “semana” con
mutate()
, utilizandofloor_date()
conunit = "week"
Obtener el recuento de filas (casos) por semana con
count()
; filtra los casos a los que les falte la fechaTermina con
complete()
de tidyr para asegurarte que todas las semanas aparecen en los datos - incluso las que no tienen filas/casos. Por defecto, los valores de recuento para cualquier fila “nueva” son NA, pero puedes hacerlos 0 con el argumentofill =
, que espera una lista con nombre (abajo,n
es el nombre de la columna de recuentos).
# Hacer un conjunto de datos agregados con los recuentos semanales de casos
<- linelist %>%
weekly_counts drop_na(date_onset) %>% # eliminar los casos sin fecha de inicio
mutate(weekly_cases = floor_date( # crear columna nueva, semana de inicio
date_onset,unit = "week")) %>%
count(weekly_cases) %>% # agrupar datos por semana y contar filas por grupo (crea columna 'n')
::complete( # asegúrar que todas las semanas están presentes, incluso aquellas en las que no se ha notificado ningún caso
tidyrweekly_cases = seq.Date( # redefinir la columna "weekly_cases" como una secuencia completa,
from = min(weekly_cases), # desde la fecha mínima
to = max(weekly_cases), # hasta la fecha máxima
by = "week"), # por semanas
fill = list(n = 0)) # rellenar los NA de la columna n con 0
Aquí están las primeras filas del dataframe resultante:
Alternativas a Epiweek
Ten en cuenta que lubridate también tiene las funciones week()
, epiweek()
, e isoweek()
, cada una de las cuales tiene fechas de inicio ligeramente diferentes y otros matices. Sin embargo, en términos generales, floor_date()
debería ser todo lo que necesitas. Puedes leer más detalles de estas funciones introduciendo ?week en la consola o leyendo la documentación aquí.
Puedes usar del paquete aweek para establecer semanas epidemiológicas. Puedes leer más sobre él en el sitio web de RECON. Tiene las funciones date2week()
y week2date()
en las que se puede establecer el día de inicio de la semana con week_start = "Monday"
. Este paquete es el más fácil si se desea obtener resultados del tipo “week” (por ejemplo, “2020-W12”). Otra ventaja de aweek es que cuando date2week()
se aplica a una columna de fecha, la columna devuelta (formato de semana) es automáticamente del tipo Factor e incluye niveles para todas las semanas en el lapso de tiempo (esto evita el paso extra de complete()
descrito anteriormente). Sin embargo, aweek no tiene la funcionalidad de redondear fechas a otras unidades de tiempo como meses, años, etc.
Otra alternativa para las series temporales que también funciona bien para mostrar un formato de “semana” (“2020 W12”) es yearweek()
del paquete tsibble, como se demuestra en la página sobre series temporales y detección de brotes.
9.10 Conversión de fechas/zonas horarias
Cuando los datos están presentes en diferentes husos horarios, a menudo puede ser importante normalizar estos datos en un huso horario unificado. Esto puede suponer un reto adicional, ya que el componente de zona horaria de los datos debe codificarse manualmente en la mayoría de los casos.
En R, cada objeto datetime tiene un componente de zona horaria. Por defecto, todos los objetos datetime
llevarán la zona horaria local para el ordenador que se está utilizando - esto es generalmente específico para una ubicación en lugar de una zona horaria, ya que las zonas horarias a menudo cambian en los lugares debido al horario de verano. No es posible compensar con precisión las zonas horarias sin un componente de tiempo de una fecha, ya que el evento que representa una columna de fecha no puede ser atribuido a un tiempo específico, y por lo tanto los cambios de tiempo medidos en horas no pueden ser razonablemente contabilizados.
Para tratar las zonas horarias, hay una serie de funciones de ayuda en lubridate que pueden utilizarse para cambiar la zona horaria de un objeto datetime
de la zona horaria local a una zona horaria diferente. Las zonas horarias se establecen atribuyendo una zona horaria válida de la base de datos tz al objeto datetime
. Aquí se puede encontrar una lista de éstas - si la ubicación que se está utilizando en los datos no está en esta lista, las grandes ciudades cercanas en la zona horaria están disponibles y sirven para el mismo propósito.
# asignar la hora actual a una columna
<- Sys.time()
time_now time_now
[1] "2024-09-18 21:38:14 +07"
# usa with_tz() para asignar una nueva zona horaria a la columna, mientras CAMBIA la hora del reloj
<- with_tz(time_now, "Europe/London")
time_london_real
# use force_tz() para asignar una nueva zona horaria a la columna, y MANTIENE la hora del reloj
<- force_tz(time_now, "Europe/London")
time_london_local
# siempre y cuando el equipo que se utilizó para ejecutar este código NO TIENE la hora de Londres,
# habrá una diferencia en los tiempos
# (el número de horas de diferencia entre la zona horaria del ordenador y Londres)
- time_london_local time_london_real
Time difference of -6 hours
Esto puede parecer muy abstracto, y a menudo no es necesario si el usuario no está trabajando en distintas zonas horarias.
9.11 Cálculos de retardo y de avance
lead()
y lag()
son funciones del paquete dplyr que ayudan a encontrar los valores anteriores (retardados) o posteriores (principales) en un vector, normalmente un vector numérico o de fechas. Esto es útil cuando se hacen cálculos de cambio/diferencia entre unidades de tiempo.`
Supongamos que se quiere calcular la diferencia de casos entre una semana actual y la anterior. Los datos se proporcionan inicialmente en recuentos semanales, como se muestra a continuación.
Al utilizar lag() o lead(), el orden de las filas en el dataframe es muy importante. - presta atención a si tus fechas/números son ascendentes o descendentes
En primer lugar, crea una nueva columna que contenga el valor de la semana anterior (retardada).
Controla el número de unidades hacia atrás/adelante con n = (debe ser un entero no negativo)
Utiliza
default =
para definir el valor colocado en las filas no existentes (por ejemplo, la primera fila para la que no hay un valor retardado). Por defecto esNA
.Utiliza
order_by = TRUE
si tus filas no están ordenadas por su columna de referencia
<- counts %>%
counts mutate(cases_prev_wk = lag(cases_wk, n = 1))
A continuación, crea una nueva columna que sea la diferencia entre las dos columnas de los casos:
<- counts %>%
counts mutate(cases_prev_wk = lag(cases_wk, n = 1),
case_diff = cases_wk - cases_prev_wk)
Puedes leer más sobre lead()
y lag()
en esta documentación aquí o introduciendo ?lag
en tu consola.
9.12 Recursos
Página de lubridate** tidyverse
Página de lubridate RStudio cheatsheet
R for Data Science en español sobre [fechas y horas]https://es.r4ds.hadley.nz/fechas-y-horas.html