INTRODUCCIÓN
Este Trabajo es una adaptación de un artículo publicado por Oscar Perpiñán Lamigueiro publicado en R-bloggers cuyo enlace encontrareis al final del artículo.En este estudio abordaremos las distintas formas de representar graficamente series temporales. Se trata de un proceso vital ya que nos permite identificar a simple vista, cambios significativos en las variables cuantitativas objeto de nuestro estudio, además de mostrarnos su evolución en el tiempo. Podemos definir como una serie temporal a un conjunto de datos, pertenecientes a una determinada variable que se representan consecutivamente durante un periodo temporal.
Para graficar de forma clara y entendible estas series temporales, usualmente se toma en el eje X la variable tiempo que no es más que una evolución constante del tiempo.Mientras que en el eje y se representa la evolución de nuestra variable objeto de estudio.
El primer paso para empezar a visualizar los datos es obtener las herramientas necesarias para ello. R nos ofrece multiples librerias que usaremos para graficar la serie temporal. Debemos descargar las liberias ggplot2, lattice y latticeExtra
CONFIGURACIÓN Y CARGA DE LIBRERIAS
library(ggplot2)
library(lattice)
#Es necesaria que la librería ggplot esté cargada de manera previa a a cargar LatticeExtra.
library(latticeExtra)
library(RColorBrewer)
#Configuración de lattice y latticeExtra
myTheme <- custom.theme.2(pch=18, cex=0.7, region=rev(brewer.pal(9, 'YlOrRd')),
symbol=brewer.pal(n=8, name="Dark2"))
myTheme$strip.background$col = myTheme$strip.shingle$col =
myTheme$strip.border$col = 'transparent'
myArgs <- list(as.table=TRUE, between=list(x=0.5, y=0.2),
xscale.components = function(...)
modifyList(xscale.components.default(...),list(top=FALSE)),
yscale.components = function(...)
modifyList(yscale.components.default(...),list(right=FALSE)))
lattice.options(default.theme=myTheme, default.args=modifyList(lattice.options()$default.args, myArgs))
Antes de seguir debemos tener en cuenta una consideración sobre la escala de nuestras variables. Tenemos que diferenciar entre las variables con una misma escala y las que tienen distinstas escalas. En el caso de que tengan la misma escala las variables aparecerán superpuestas mietras que en el caso contrario, se hará un gráfico para cada variable cuya escala sea distinta.
SERIE TEMPORAL CON DISTINTAS ESCALAS
# Cargamos nuestros datos
library(zoo)
load('aranjuez.Rdata')
xyplot(aranjuez, layout = c(1, ncol(aranjuez)))
Una alternativa a la visualización de los datos es con la librería ggplot, el comando autoplot().
SERIE TEMPORAL CON LA MISMA ESCALA
load('navarra.Rdata')
avRad <- zoo(rowMeans(navarra, na.rm = 1), index(navarra))
pNavarra <- xyplot(navarra - avRad,
superpose = TRUE, auto.key = FALSE,
lwd = 0.5, alpha = 0.3, col = 'orange')
pNavarra
Ahora vamos a realizar una visualización de los datos en la que se va a graficar cada serie en una fila.
Hay que destacar que con el argumento de origin=0 y horizonscale,que se establece de manera predeterminada, se va a conseguir que cada una de las filas adquiera un formato y una escala diferentes.
horizonplot(navarra - avRad,
layout = c(1, ncol(navarra)),
origin = 0, ## Deviations in each panel are calculated
## from this value
colorkey = TRUE,
col.regions = brewer.pal(6, "RdBu"))
Los gráficos de horizonte nos ayudan a detectar de una manera más eficaz las diferencias entre una serie temporal univariante y otras referencias que se hagan.
Para entender mejor esta idea vamos a poner el ejemplo en el que se quiere conocer la variación o cambio de temperatura a lo largo de los dias en la estación de Aranjuez. Dicha variación se va a calcular con el comando ave
Ta <- aranjuez$TempAvg
timeIndex <- index(aranjuez)
longTa <- ave(Ta, format(timeIndex, '%j'))
diffTa <- (Ta - longTa)
# Con el comando de horizonplot, con el método cut, vamos a poder hacer una distinción entre los años
years <- unique(format(timeIndex, '%Y'))
horizonplot(diffTa, cut = list(n = 8, overlap = 0),
colorkey = TRUE, layout = c(1, 8),
scales = list(draw = FALSE, y = list(relation = 'same')),
origin = 0, strip.left = FALSE) +
layer(grid.text(years[panel.number()], x = 0, y = 0.1,
gp = gpar(cex = 0.8),
just = "left"))GRÁFICOS INTERACTIVOS
En este apartado se van a incluir gráficos interactivos como alternativa a los gráficos estaticos que hemos visto previamente. Para realizarlos tenemos que cargar las siguientes librerias de manera previa: dygraphs, highcharter, and plotly .
Digraphs
Este paquete es una interfaz de la libreria dygraphs de Javascript, y nos facilita la posibilidad de representación de series temporales.
Funciona de una manera automática con los objetos del tipo xts, o del tipo de objetos que puedan ser transformados a este tipo. El resultado que nos proporciona son gráficos interactivos, dónde los valores se muestran en función de la posición del ratón sobre la serie temporal.
library(dygraphs)
library(widgetframe)
dyTemp <- dygraph(aranjuez[, c("TempMin", "TempAvg", "TempMax")],
main = "Temperature in Aranjuez",
ylab = "ºC")
dyTempHay que tener en cuenta que se pueden optimizar estos gráficos con el uso de pipelines. Estos son una manera de hacer referéncia al objeto anterior, sin necesidad de ir guardándolo y hacer referéncia sobre los nuevos objetos resultantes. Vamos a verlo con el siguiente ejemplo. Además, dyOptions nos proporciona muchas opciones de diseño de gráficos, además con el dyHighlight nos permite modificar las opciones del ratón sobre la serie temporal.
gf<-dyTemp %>%
dyHighlight(highlightSeriesBackgroundAlpha = 0.2,
highlightSeriesOpts = list(strokeWidth = 2))
gfOtra alternativa para la representacón de los puntos máximos y mínimos de las variables de las series temporales es con sombreado de las regiones. dySeries es una función que admite un vector de caráteres de longitud 3, que nos especifica un conjunto de nombres para usar como punto mínimos, medios y superiores, sombreando una zona a su alrededor.
grz<-dygraph(aranjuez[, c("TempMin", "TempAvg", "TempMax")],
main = "Temperature in Aranjuez",
ylab = "ºC") %>%
dySeries(c("TempMin", "TempAvg", "TempMax"),
label = "Temperature")
grzHighcharter
Este paquete Highcharter posee una gran variedad de soluciones gráficas. Para realizar la representación de series temporales con este comando se puede hacer combinando la función geérica de highchart y otras llamadas sucesivas a la función hc_add_series_xts con los anteriormente mencionados pipelines.
library(highcharter)
library(xts)
aranjuezXTS <- as.xts(aranjuez)
gr<-highchart() %>%
hc_add_series(name = 'TempMax',
aranjuezXTS[, "TempMax"]) %>%
hc_add_series(name = 'TempMin',
aranjuezXTS[, "TempMin"]) %>%
hc_add_series(name = 'TempAvg',
aranjuezXTS[, "TempAvg"])
grPlotly
Este paquete no proporciona ninguna función especial para la representación de series. Pero, hay que tener en cuenta que la serie temporal tiene que ser transformada en un data frame, incluyendo una columna para el índice temporal.
En el caso de que el data frame tenga un formato amplio, es decir, hay una columna para cada variable, cada una de estas va a ser representada llamando a la función add_lines .
Por otra parte, si nuestro data frame está en formato largo, una columna para los valores y otra para los nombres de las variables, solo se requerirá llamar a la función una única vez.
En el siguiente ejemplo, vamos a hacer un ejemplo para mostrarlo de una manera práctica,convirtiendo el objeto zoo en un data frame, mediante la librería fortify , y melt . para convertirlo de un formato amplio a uno largo.
library(plotly)
aranjuezDF <- fortify(aranjuez[,
c("TempMax",
"TempAvg",
"TempMin")],
melt = TRUE)
summary(aranjuezDF) TRUE Index Series Value
TRUE Min. :2004-01-01 TempMax:2898 Min. :-12.980
TRUE 1st Qu.:2005-12-29 TempAvg:2898 1st Qu.: 7.107
TRUE Median :2008-01-09 TempMin:2898 Median : 13.560
TRUE Mean :2008-01-03 Mean : 14.617
TRUE 3rd Qu.:2010-01-03 3rd Qu.: 21.670
TRUE Max. :2011-12-31 Max. : 41.910
TRUE NA's :10
EL TIEMPO COMO CONDICIONANTE O VARIABLE AGRUPADORA
De manera previa hemos estado analizando la evolución de múltiples series temporales con diferentes escalas.Pero, y si lo que realmente nos interesa es representar la relación entre las variables? En los siguientes apartados vamos a hacer varios gráficos, teniendo en cuenta si se trata del tiempo como factor para agrupar variables o como un condicionante sobre las variables.
Matriz de Gráficos de Dispersión, el tiempo como variable agrupadora
Este tipo de gráficos se basa en la representación conjunta de pequeños gráficos independientes ilustrados a la vez, lo que nos permite hacer comparaciones entre las distintas variables de trabajo.
Este tipo de gráficos esta implemnetado en la función splom .
aranjuezDF <- data.frame(aranjuez)
aranjuezDF$Month <- format(index(aranjuez), '%m')
## Red-Blue palette with black added (12 colors)
colors <- c(brewer.pal(n = 11, 'RdBu'), '#000000')
## Rearrange according to months (darkest for summer)
colors <- colors[c(6:1, 12:7)]
splom(~ aranjuezDF[1:10], ## no incluimos "Month"
groups = aranjuezDF$Month,
auto.key = list(space = 'right',
title = 'Month', cex.title = 1),
pscale = 0, varname.cex = 0.7, xlab = '',
par.settings = custom.theme(symbol = colors,
pch = 19),
cex = 0.3, alpha = 0.1)La versión de este gráfico producida por ggplot2 se genera con la función ggpairs que requiere instalar el paquete GGally
library(GGally)
ggpairs(aranjuezDF,
columns = 1:10, ## no incluimos "Month"
upper = list(continuous = "points"),
mapping = aes(colour = Month, alpha = 0.1))
En este tipo de gráficos separamos los datos por meses y además incluimos algunas variables desriptivas (media,máximo y mínimo) como condicionantes.
Para poder conseguir el formato deseado de los datos y que cumpla lo anteriormente dicho, tenemos que usar el comando melt del paquete reshape2 .
library(reshape2)
aranjuezRshp <- melt(aranjuezDF,
measure.vars = c('TempMax',
'TempAvg',
'TempMin'),
variable.name = 'Statistic',
value.name = 'Temperature')Ahora ya podemos realizar los gráficos oportunos:
ggplot(data = aranjuezRshp, aes(Radiation, Temperature)) +
facet_grid(Statistic ~ Month) +
geom_point(col = 'skyblue4', pch = 19, cex = 0.5, alpha = 0.3) +
geom_rug() +
stat_smooth(se = FALSE, method = 'loess',
col = 'indianred1', lwd = 1.2) +
theme_bw() Realizamos el mismo gráfico con la variante que nos otorga lattice .
library(latticeExtra)
useOuterStrips(
xyplot(Temperature ~ Radiation | Month * Statistic,
data = aranjuezRshp,
between = list(x = 0),
col = 'skyblue4', pch = 19,
cex = 0.5, alpha = 0.3)) +
layer({
panel.rug(..., col.line = 'indianred1',
end = 0.05, alpha = 0.6)
panel.loess(..., col = 'indianred1',
lwd = 1.5, alpha = 1)
}) EL TIEMPO COMO VARIABLE COMPLEMENTARIA
En este apartado vamos a utilizar el tiempo como una variable auxiliar que añade información al gráfico donde otras variables serán confrontadas. En nustro caso enfrentaremos la renta nacional bruta(GNI) y las emisiones de CO2 de un grupo de países.Trataremos de representar la relación entre ambas variables durante un periodo de 14 años,con el propio tiempo como variable auxiliar.
Representamos todos los datos en una misma ventana con un gráfico de dispersión que una los puntos en función del país de pertenencia. Para mejorar nuestro gráfico podemos cambiar colores para permitir una visualización más sencilla,también podemos añadir etiquetas con los años para cada observación y por último añadir a cada línea una etiqueta con el país al que pertenecen esos datos.
load('CO2.Rdata')
nCountries <- nlevels(CO2data$Country.Name)
pal <- brewer.pal(n = 5, 'Set1')
pal <- rep(pal, length = nCountries)
#fin de la selección de colores
CO2mean <- aggregate(CO2.capita ~ Country.Name,
data = CO2data, FUN = mean)
palOrdered <- pal[rank(CO2mean$CO2.capita)]
myTheme <- simpleTheme(pch = 19, cex = 0.6, col = palOrdered)
pCO2.capita <- xyplot(GNI.capita ~ CO2.capita,
data = CO2data,
xlab = "Carbon dioxide emissions (metric tons per capita)",
ylab = "GNI per capita, PPP (current international $)",
groups = Country.Name,
par.settings = myTheme,
type = 'b')
#añadimos la etiqueta de los años
pCO2.capita <- pCO2.capita +
glayer_(panel.text(...,
labels = CO2data$Year[subscripts],
pos = 2, cex = 0.5, col = 'gray'))GRÁFICOS INTERACTIVOS:ANIMACIONES
load('CO2.Rdata')
p <- plot_ly(CO2data,
x = ~CO2.capita,
y = ~GNI.capita,
sizes = c(10, 100),
marker = list(opacity = 0.7,
sizemode = 'diameter'))
p <- add_markers(p,
size = ~CO2.PPP,
color = ~Country.Name,
text = ~Country.Name, hoverinfo = "text",
ids = ~Country.Name,
frame = ~Year,
showlegend = FALSE)
p <- animation_opts(p,
frame = 1000,
transition = 800,
redraw = FALSE)
p <- animation_slider(p,
currentvalue = list(prefix = "Year "))
p