Introducción

R proporciona varias opciones para tratar con datos de fecha y fecha/hora. La función as.Date del paquete base maneja las fechas pero sin tiempos, existe el paquete chron que trabaja con fecha y tiempos, pero no controla la zona horaria; y las clases POSIXct y POSIXlt, que incorpora la norma POSIX, sirven para trabajar con tiempo fechas y zonas horarias.

install.packages("chron",dependencies = T)
Sys.Date()
## [1] "2020-07-14"
Sys.time()
## [1] "2020-07-14 19:53:40 -05"
Sys.timezone()
## [1] "America/Bogota"
Sys.getlocale()
## [1] "LC_COLLATE=Spanish_Colombia.1252;LC_CTYPE=Spanish_Colombia.1252;LC_MONETARY=Spanish_Colombia.1252;LC_NUMERIC=C;LC_TIME=Spanish_Colombia.1252"
methods(as.Date)
## [1] as.Date.character as.Date.default   as.Date.factor    as.Date.numeric  
## [5] as.Date.POSIXct   as.Date.POSIXlt  
## see '?methods' for accessing help and source code
args(as.Date.character)
## function (x, format, tryFormats = c("%Y-%m-%d", "%Y/%m/%d"), 
##     optional = FALSE, ...) 
## NULL

El argumento format= indica el tipo de formato de fecha que se quiere usar.

  • %d: día del mes (número decimal)
  • %m: Mes (número decimal)
  • %b: Mes (nombre abreviado)
  • %B: Mes (nombre completo)
  • %y: Año (dos dígitos)
  • %Y: Año (cuatro dígitos)
as.Date("1949-8-26")
## [1] "1949-08-26"
as.Date("1985/10/15")
## [1] "1985-10-15"
as.Date("6/18/1932", format="%m/%d/%Y")
## [1] "1932-06-18"
as.Date("Mayo 1, 1886", format="%B %d, %Y")
## [1] "1886-05-01"
as.Date("15mar.92", format="%d%b%y")
## [1] "1992-03-15"

Internamente los objetos tipo Date guarda un número de días comenzando desde Enero 01 de 1970, con la función as.numeric se puede coercionar la fecha para convertirla en número.

x <- c("1960-1-1","1969-1-1","1970-1-1","1971-1-1","1980-1-1")
(y <- as.Date(x))
## [1] "1960-01-01" "1969-01-01" "1970-01-01" "1971-01-01" "1980-01-01"
as.numeric(y)
## [1] -3653  -365     0   365  3652

Para extraer los componentes de fechas se puede emplear las funciones weekdays, months, days o quarters.

# Fechas de nacimiento de Estadísticos importantes en la historia
library(chron)
(Dnac <- c(tukey=as.Date('1915-06-16'),fisher=as.Date('1890-02-17'),
          cramer=as.Date('1893-09-25'),kendall=as.Date('1907-09-06')))
##        tukey       fisher       cramer      kendall 
## "1915-06-16" "1890-02-17" "1893-09-25" "1907-09-06"
weekdays(Dnac)
##       tukey      fisher      cramer     kendall 
## "miércoles"     "lunes"     "lunes"   "viernes"
months(Dnac)
##        tukey       fisher       cramer      kendall 
##      "junio"    "febrero" "septiembre" "septiembre"
days(Dnac)
## [1] 16 17 25 6 
## 31 Levels: 1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < 11 < 12 < 13 < ... < 31
quarters(Dnac)
## [1] "Q2" "Q1" "Q3" "Q3"

La función chron sirve para trabaja con fechas y tiempos, los formatos que reciben son.

Fechas

  • m: Mes (número decimal)
  • d: Días del mes (número decimal)
  • y: Año (cuatro dígitos)
  • mon: Mes (nombre abreviado)
  • month: Mes (nombre completo)

Tiempos

  • h: Hora
  • m: Minutos
  • s: Segundos
(fechas <- dates(c("06/09/02","01/29/03",
                  "09/04/02","11/13/02",
                  "07/07/02")))
## [1] 06/09/02 01/29/03 09/04/02 11/13/02 07/07/02
(tiempos <- times(c("12:45:40","09:30:40",
                    "16:45:40","20:00:40",
                    "17:30:40")))
## [1] 12:45:40 09:30:40 16:45:40 20:00:40 17:30:40
chron(dates. = fechas, times. = tiempos)
## [1] (06/09/02 12:45:40) (01/29/03 09:30:40) (09/04/02 16:45:40)
## [4] (11/13/02 20:00:40) (07/07/02 17:30:40)
chron(dates. = fechas, times. = tiempos,format = c("y-m-d","h:m:s"))
## [1] (02-06-09 12:45:40) (03-01-29 09:30:40) (02-09-04 16:45:40)
## [4] (02-11-13 20:00:40) (02-07-07 17:30:40)
chron(dates. = fechas, times. = tiempos,format = c("y-month-d","h:m:s"))
## [1] (2002-June-09 12:45:40)      (2003-January-29 09:30:40)  
## [3] (2002-September-04 16:45:40) (2002-November-13 20:00:40) 
## [5] (2002-July-07 17:30:40)

Hay dos clases de fecha/hora de tipo POSIX, que difieren en la forma en que los valores se almacenan internamente. La clase POSIXct almacena los valores fecha/hora como el número de segundos desde el 1 de Enero de 1970, mientras que la clase POSIXlt los almacena como una lista con elementos para el segundo, minuto, hora, día, mes y año, entre otros. A menos que necesite la naturaleza de lista de la clase POSIXlt, la clase POSIXct es la opción habitual para almacenar fechas en R.

El formato de entrada predeterminado para las fechas POSIX consiste en el año, seguido del mes y el día, separados por barras o guiones; para los valores de fecha/hora, la fecha puede ir seguida de un espacio en blanco y una hora en la forma hora:minutos:segundos o hora:minutos.

dts <- c ("2005-10-21 18:47:22", "2005-12-24 16:39:58",
           "2005-10-28 07:30:05 PDT") 
as.POSIXlt(dts)
## [1] "2005-10-21 18:47:22 -05" "2005-12-24 16:39:58 -05"
## [3] "2005-10-28 07:30:05 -05"

Si la fecha/hora de entrada se almacenan como el número de segundos desde el 1 de Enero de 1970, puede crear valores de fecha POSIX asignando la clase apropiada directamente a esos valores. Dado que la mayoría de las funciones de manipulación de fechas se refieren a la clase psuedo POSIXt, asegúrese de incluirla como el primer miembro del atributo de clase.

dts <- c(1127056501,1104295502,1129233601,1113547501,
         1119826801,1132519502,1125298801,1113289201)
mydates <- dts 
class(mydates) <- c('POSIXt','POSIXct') 
mydates
## [1] "2005-09-18 10:15:01 -05" "2004-12-28 23:45:02 -05"
## [3] "2005-10-13 15:00:01 -05" "2005-04-15 01:45:01 -05"
## [5] "2005-06-26 18:00:01 -05" "2005-11-20 15:45:02 -05"
## [7] "2005-08-29 02:00:01 -05" "2005-04-12 02:00:01 -05"
  • %a: Día de la semana abreviado
  • %A: Día de la semana completo
  • %b: Mes abreviado
  • %B: Mes completo
  • %c: Fecha y hora específicas de la localidad
  • %d: Fecha decimal
  • %H: Horas decimales (24 horas)
  • %I: Horas decimales (12 horas)
  • %j: Día decimal del año
  • %m: Mes decimal
  • %M: Minuto decimal
  • %p: Localidad específica de AM/PM
  • %S: Segundo decimal
  • %U: Decimal semana del año (a partir del domingo)
  • %w: Decimal día de la semana (0 = domingo)
  • %W: Decimal semana del año (a partir del lunes)
  • %x: Fecha específica de la localidad
  • %X: Tiempo específico de la localidad
  • %y: Año de 2 dígitos
  • %Y: Año de 4 dígitos
  • %z: Comparación con GMT
  • %Z: Zona horaria (character)
args(strptime)
## function (x, format, tz = "") 
## NULL
args(ISOdate)
## function (year, month, day, hour = 12, min = 0, sec = 0, tz = "GMT") 
## NULL
strptime('16/Oct/2005:07:51:00',format='%d/%b/%Y:%H:%M:%S')
## [1] NA
ISOdate(2005,10,21,18,47,22,tz="PDT")
## [1] "2005-10-21 18:47:22 GMT"
data.frame(OlsonNames())
(fecha <- ISOdate(2005, 10, 21, 18, 47, 22, tz = "VEN"))
## [1] "2005-10-21 18:47:22 GMT"
format(fecha,'%A, %B %d, %Y %H:%M:%S')
## [1] "viernes, octubre 21, 2005 18:47:22"
(b1 <- ISOdate(1977,7,13))
## [1] "1977-07-13 12:00:00 GMT"
(b2 <- ISOdate(2003,8,14))
## [1] "2003-08-14 12:00:00 GMT"
b2 - b1
## Time difference of 9528 days
difftime(b2,b1,units='weeks')
## Time difference of 1361.143 weeks
difftime(b2,b1,units='mins')
## Time difference of 13720320 mins
difftime(b2,b1,units='secs')
## Time difference of 823219200 secs
seq(as.Date('1976-7-4'),by='days',length=10)
##  [1] "1976-07-04" "1976-07-05" "1976-07-06" "1976-07-07" "1976-07-08"
##  [6] "1976-07-09" "1976-07-10" "1976-07-11" "1976-07-12" "1976-07-13"
seq(as.Date('1976-7-4'),by='years',length=10)
##  [1] "1976-07-04" "1977-07-04" "1978-07-04" "1979-07-04" "1980-07-04"
##  [6] "1981-07-04" "1982-07-04" "1983-07-04" "1984-07-04" "1985-07-04"
seq(as.Date('2000-6-1'),to=as.Date('2000-8-1'),by='2 weeks')
## [1] "2000-06-01" "2000-06-15" "2000-06-29" "2000-07-13" "2000-07-27"

Paquete lubridate

El paquete lubridate es parte de la familia tidyverse, según sus autores “lubridate tiene una sintaxis consistente y memorable, que hace que trabajar con las fechas sea divertido en lugar de frustrante”."

install.packages("lubridate", dependencies = T)
library(lubridate)
(hoy <- today())
## [1] "2020-07-14"
year(hoy)
## [1] 2020
month(hoy)
## [1] 7
day(hoy)
## [1] 14
wday(hoy)
## [1] 3
wday(hoy,label = T)
## [1] mar\\.
## Levels: dom\\. < lun\\. < mar\\. < mié\\. < jue\\. < vie\\. < sáb\\.
mday(hoy)
## [1] 14
yday(hoy)
## [1] 196
(ya <- now())
## [1] "2020-07-14 19:53:41 -05"
hour(ya)
## [1] 19
minute(ya)
## [1] 53
second(ya)
## [1] 41.69896
(fecha <- ymd("1979-06-12"))
## [1] "1979-06-12"
class(fecha)
## [1] "Date"
ymd("1989 May 17")
## [1] "1989-05-17"
mdy("March 12, 1975")
## [1] "1975-03-12"
dmy(25081985)
## [1] "1985-08-25"
ymd("1920/1/2")
## [1] "1920-01-02"
dt1 <- '2014-08-23 17:23:02'
ymd_hms(dt1)
## [1] "2014-08-23 17:23:02 UTC"
hms("03:22:14")
## [1] "3H 22M 14S"
update(ya, hours = 8, minutes = 34, seconds = 55)
## [1] "2020-07-14 08:34:55 -05"
update(ymd_hms(dt1),year=2019,hours=12,minutes=56,seconds=24)
## [1] "2019-08-23 12:56:24 UTC"
now("America/New_York")
## [1] "2020-07-14 20:53:41 EDT"
now("Japan")
## [1] "2020-07-15 09:53:41 JST"
now("Europe/Andorra")
## [1] "2020-07-15 02:53:41 CEST"
(CABA <- now("America/Buenos_Aires"))
## [1] "2020-07-14 21:53:41 -03"
CABA + days(2)
## [1] "2020-07-16 21:53:41 -03"
CABA + hours(10) + minutes(35)
## [1] "2020-07-15 08:28:41 -03"
with_tz(CABA,"US/Alaska")
## [1] "2020-07-14 16:53:41 AKDT"
with_tz(CABA + hours(10) + minutes(35),"America/Bogota")
## [1] "2020-07-15 06:28:41 -05"
(antes <- mdy("06-17-2008", tz = "Singapore"))
## [1] "2008-06-17 +08"
(cuanto <- interval(antes,CABA))
## [1] 2008-06-17 +08--2020-07-15 08:53:41 +08
as.period(cuanto)
## [1] "12y 0m 28d 8H 53M 41.7669699192047S"
antes %--% CABA
## [1] 2008-06-17 +08--2020-07-15 08:53:41 +08
as.duration(cuanto)
## [1] "381142421.76697s (~12.08 years)"
cuanto/dweeks(1)
## [1] 630.1958
cuanto/dweeks(5)
## [1] 126.0392
cuanto/dhours(1)
## [1] 105872.9
cuanto/dhours(12)
## [1] 8822.741
cuanto/dminutes(1)
## [1] 6352374
cuanto/dminutes(30)
## [1] 211745.8
cuanto/dyears(1)
## [1] 12.07767
cuanto/dyears(3)
## [1] 4.025892
start <- c("2012-08-21", "2012-09-01", "2012-08-15", "2012-09-18")
end <- c("2012-09-16", "2012-09-06", "2012-08-22", "2012-10-11")
(elapsed.time <- start %--% end)
## [1] 2012-08-21 UTC--2012-09-16 UTC 2012-09-01 UTC--2012-09-06 UTC
## [3] 2012-08-15 UTC--2012-08-22 UTC 2012-09-18 UTC--2012-10-11 UTC
mean(as.duration(elapsed.time) / dweeks(1))
## [1] 2.178571

Ejemplo

La siguiente base de datos es una recolección de registros de temperatura de un río cada 15 minutos realizada por el NF American River. Este conjunto de datos tiene 35.038 observaciones de temperatura del agua y etapa (información del transductor de presión).

datos <- read.csv("https://raw.githubusercontent.com/gge-ucd/wRangling_Seminar/master/data/2015_NFA_solinst_08_05.csv", skip=13)
library(lubridate)
library(dplyr)
datos
summary(datos)
##          Date             Time             ms        Level       
##  2014/08/06:   96   00:00:00:  365   Min.   :0   Min.   :0.7718  
##  2014/08/07:   96   00:15:00:  365   1st Qu.:0   1st Qu.:1.1190  
##  2014/08/08:   96   00:30:00:  365   Median :0   Median :1.3135  
##  2014/08/09:   96   00:45:00:  365   Mean   :0   Mean   :1.3791  
##  2014/08/10:   96   01:00:00:  365   3rd Qu.:0   3rd Qu.:1.5235  
##  2014/08/11:   96   01:15:00:  365   Max.   :0   Max.   :4.7376  
##  (Other)   :34462   (Other) :32848                               
##   Temperature    
##  Min.   : 1.724  
##  1st Qu.: 8.197  
##  Median :13.258  
##  Mean   :14.291  
##  3rd Qu.:20.960  
##  Max.   :28.748  
## 
names(datos)
## [1] "Date"        "Time"        "ms"          "Level"       "Temperature"
datos$datetime <- paste0(datos$Date, " ", datos$Time)
datos$datetime <- ymd_hms(datos$datetime)
library(magrittr) # para usar " %<>% "
library(ggplot2)
datos %<>% # Qué hace esto?
  mutate(yr = year(datetime),
         mon = month(datetime),
         wk = week(datetime),
         DOY = yday(datetime),
         hr = hour(datetime))
datos
datos %>%  select(Level, Temperature, wk) %>%
  group_by(wk) %>% 
  summarise_each(funs(mean, max, min)) %>%
  ggplot() +
  geom_point(aes(x=wk,y=Temperature_max),color="gray40",fill="maroon",pch=21)+
  geom_line(aes(x=wk,y=Temperature_mean),color="red3")+
  geom_point(aes(x=wk,y=Temperature_min),color="gray40",fill="navyblue",pch=21)+
  xlab("July 2015: Week")

datos %>%  filter(mon>=4 & mon<=6) %>% 
  select(Level, DOY, hr, yr) %>%
  group_by(yr, DOY, hr) %>% 
  summarise(mean_Level=mean(Level)) %>% 
  mutate(datetimes = ymd_hms(strptime(paste0(yr,"-",DOY," ",hr, ":00"),format="%Y-%j %H:%M"))) %>% 
  ggplot()+
  geom_line(aes(x=datetimes, y=mean_Level),color="forestgreen")+
  xlab("Date") + ylab("Hourly Stage (m)")

datos %>%  
  select(Temperature, mon) %>%
  group_by(mon) %>% 
  summarise_each(funs(mean, max, min)) %>%
  ggplot()+
  geom_pointrange(aes(x=mon,y=mean,ymax=max,ymin=min),fill="maroon",size=1,pch=21)+
  xlab("Avg Monthly Water Temperature: Months")

En los siguientes links se encuentran guías útiles para trabajar modelos series de tiempo.