26 mar 2018

Trabajando con fechas en R (I)

Esta entrada se elabora con el objetivo de dar respuesta a interrogantes que surgieron en el curso de "Análisis estadístico y pronósticos" impartido por Empírica, referidas al manejo de fechas en R para el análisis de estacionalidad de series temporales a partir de que R pueda identificar vectores de fechas introducidas en formato texto (cadena).

La función strptime permite transformar un objeto tipo cadena en una fecha. Es decir, toma como argumento un objeto tipo texto y lo transforma en uno tipo date, de forma tal que lo reconoce como una fehca, con un determinado formato:

x<-c("2008-01-01 02:30:15")
strptime(x, format="%Y-%m-%d %H:%M:%S")
[1] "2008-01-01 02:30:15 -0430"

De forma análoga, se pueden incorporar datos cargados a R desde otras plataformas como Excel. En este caso hemos importado el documento ExcelFechas.txt que contiene un vector de fecha generado en Excel, conjuntamente con una columna llamada "prec" de valores aleatorios de una normal, también generados en Excel.

Gráficos de línea con etiquetas de fecha en sus ejes

precios <- read.delim("ExcelFechas.txt")
attach(precios)

> fecha[1]
[1] 30/10/2012 3:18:02
1598 Levels: 1/1/2013 3:18:02 1/1/2014 3:18:02 ... 9/9/2016 3:18:02

De forma que indicando a R el formato del vector de fecha, podemos utilizarlo para asignarle las etiquetas de fechas a los valores del gráfico de línea que hasta ahora había aparecido con el número de las observaciones como etiqueta:

fecha1<-strptime(fecha, format="%d/%m/%Y %H:%M:%S")
plot(fecha1, pre, type = "l")

Componentes del objeto fecha

También, se pueden extraer los componentes del vector de fecha, tales como: los días de la semana, la hora, los segundos, entre otros. A continuación se muestran algunos ejemplos a partir de funciones, tomando como ejemplo la fecha contenida en la observación 500 (fecha1[500]):

> fecha1[500]
[1] "2014-03-13 03:18:02 -0430"

> months(fecha1)[500]
[1] "March"

> weekdays(fecha1)[500]
[1] "Thursday"

> quarters(fecha1)[500]
[1] "Q1"

Estos componentes, también se pueden extraer mediante la opción format:

> format(as.Date(fecha1),"%Y")[500]
[1] "2014"

> format(as.Date(fecha1),"%d")[500]
[1] "13"

Otra manera de acceder a los componentes de una fecha determinada mediante indexación:

(fecha1)[500]$min
[1] 18

# $hour $mday $mon $year $wday $yday
Tablas de estadístico por mes, año, día…

Una vez extraemos un vector cualquiera de fechas o algún componente de la misma, es fácil poder realizar operaciones con las mismas. Por ejemplo, contabilizar la cantidad de observaciones correspondientes a los diversos meses contenidos en la base de datos.

> meses<-months(fecha1)
> table(meses)
meses
April August December February January July June March
120 124 155 141 155 124 120 139
May November October September
124 150 126 120

A su vez, podemos realizar una tabla especial conteniendo el valor promedio de la variable “pre” (generada a partir de valores aleatorios para ilustrar este ejemplo) utilizando el comando tapply, que incluye operaciones vectorizadas de R para evitar el uso de bucles.

> tapply(pre, list(meses), mean)
April August December February January July June March
0.4693917 0.5218468 0.5175871 0.4665106 0.4861097 0.5163387 0.4899833 0.4929784
May November October September
0.5132177 0.4671400 0.4698095 0.5198167

Adicionalmente, se puede visualizar el análisis anterior segmentarlo por año:

ano<-format(as.Date(fecha1),"%Y")
tapply(pre, list(ano, meses), mean)
April August December February January July
2012 NA NA 0.5388387 NA NA NA
2013 0.4594333 0.5369677 0.5217742 0.4603929 0.4398387 0.5930968
2014 0.4685333 0.5244839 0.5189677 0.5590000 0.4972581 0.4159032
2015 0.4613667 0.4605161 0.5129032 0.3904643 0.5510000 0.5151935
2016 0.4882333 0.5654194 0.4954516 0.4524138 0.4621290 0.5411613
2017 NA NA NA 0.4707857 0.4803226 NA

June March May November October September
2012 NA NA NA 0.4772333 0.0755000 NA
2013 0.3931000 0.5600645 0.5402903 0.4820667 0.4639355 0.4928333
2014 0.5238333 0.4100000 0.5120323 0.4179000 0.4890968 0.5246667
2015 0.5705667 0.5619355 0.5053226 0.5215333 0.5353871 0.5090000
2016 0.4724333 0.4887419 0.4952258 0.4369667 0.4162581 0.5527667
2017 NA 0.3920667 NA NA NA NA

Se pueden representar los valores promedio mensuales en un gráfico de barra:

barplot(tapply(pre, list(meses), mean))


Recuerde que el estadístico incluido en el comando anterior [mean] puede cambiarse a otros como el máximo, el mínimo o la desviación estándar o la suma de valores (consulte la ayuda de R):

> tapply(pre, list(ano), sum)
2012 2013 2014 2015 2016 2017
31.172 181.049 178.100 185.717 179.028 33.953

Fechas para análisis estacional (generando variables dummy a partir de fechas)

También, se pueden utilizar las operaciones tradicionales de R para generar variables dummys que permitan estudiar condiciones estacionales de las series de tiempo. Por ejemplo, podemos generar una secuencia con los días del mes de enero, para posteriormente crear una dummy que sea igual a 1 los días lunes (modificar el código para extraer otros componentes como años, meses o cuatrimestre es relativamente fácil, por tanto, este análisis se puede extrapolar fácilmente para generar dummys para estas frecuencias temporales):

> diaEnero<-seq(as.Date("2010-01-01"), as.Date("2010-01-31"), by = "1 day")
> as.numeric(weekdays(diaEnero)=="Monday")
[1] 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0

Aquí es importante recordar que la indexación lógica también nos permite extraer solo los lunes, para extraer imprimir (o guardar) un nuevo vector con las observaciones que cumplen con la condición establecida. En el siguiente ejemplo extraemos los lunes:

> diaEnero[weekdays(diaEnero)=="Monday"]
[1] "2010-01-04" "2010-01-11" "2010-01-18" "2010-01-25"

Suponga además el escenario donde cuenta con un listado de fechas de días feriados o eventos puntuales identificados para el estudio de eventos, y necesitas crear una dummy que sean igual a 1 para estas fechas determinadas. Claro que esta operación se puede realizar mediante loops, pero una alternativa más simple es la de utilizar el operador especial de R %in% que permite comparar si un cierto elemento de nuestro vector es igual a los elementos de un conjunto representado por un vector.

> eventos<-c(as.Date("2010-01-7"),as.Date("2010-01-11"),as.Date("2010-01-24"))
> as.numeric(diaEnero %in% eventos)
[1] 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0

Operaciones con fechas

Se pueden generar secuencia de fecha a partir de una fecha de inicio determinada, solamente sumándole un objeto tipo vector con determinada frecuencia:

> fechita <- as.Date("2017-01-13")
> fechita + c(0:5)
[1] "2017-01-13" "2017-01-14" "2017-01-15" "2017-01-16" "2017-01-17"
[6] "2017-01-18"

También, se puede utilizar el comando seq, para generar secuencia de fechas mensuales que cumplan con una determinada longitud:

> seq(fechita[1], by="1 months", length.out=6)
[1] "2017-01-13" "2017-02-13" "2017-03-13" "2017-04-13" "2017-05-13"
[6] "2017-06-13"

Esta secuencia se puede generar con una frecuencia diaria:

> seq(as.Date("2010-01-01"), as.Date("2010-01-31"), by = "1 day")
[1] "2010-01-01" "2010-01-02" "2010-01-03" "2010-01-04"
[5] "2010-01-05" "2010-01-06" "2010-01-07" "2010-01-08"
[9] "2010-01-09" "2010-01-10" "2010-01-11" "2010-01-12"
[13] "2010-01-13" "2010-01-14" "2010-01-15" "2010-01-16"
[17] "2010-01-17" "2010-01-18" "2010-01-19" "2010-01-20"
[21] "2010-01-21" "2010-01-22" "2010-01-23" "2010-01-24"
[25] "2010-01-25" "2010-01-26" "2010-01-27" "2010-01-28"
[29] "2010-01-29" "2010-01-30" "2010-01-31"

Número de días entre dos fechas

as.Date("2010-10-01")-as.Date("2010-01-01")
Time difference of 273 days

Referencias

- Andrie de Vries, Joris Meys. HOW TO WORK WITH DATES IN R. Disponible en: http://www.dummies.com/programming/r/how-to-work-with-dates-in-r/

- Beck, Cole (2012). Handling date-times in R. Disponible en: http://biostat.mc.vanderbilt.edu/wiki/pub/Main/ColeBeck/datestimes.pdf

- Berkeley.edu (2017). Dates and Times in R. Disponible en: https://www.stat.berkeley.edu/~s133/dates.html

Recesión plot en R usando ggplot (recession plot in r)

En el siguiente ejemplo se simular y replica -parcialmente- un ejemplo usado por el FMI para ilustrar la importancia del uso de series de ti...