1 INTRODUCCIÓN A LAS SERIES TEMPORALES EN R

1.1 ¿Qué es una serie temporal?

Una serie temporal es una sucesión de observaciones de una variable tomadas en distintos momentos del tiempo. Conforman, por lo tanto, distribuciones bidimensionales en las que una de las variables es el tiempo y la otra los “casos” o sujetos, los diferentes valores de una variable medidos a lo largo de un intervalo temporal.

Estas series son muy importantes para múltiples disciplinas, entre ellas la Geografía. Ejemplos:

  • Demografía: evolución de la población, tasas de mortalidad infantil etc.

  • Medioambiente: evolución de los contaminantes medidos en una ciudad, lluvia recogida, temperatura media, residuos tóxicos en un río etc.

La forma más usual de presentar estas distribuciones es una tabla con dos columnas:

  • La variable tiempo (“variable independiente”) se representa como \(t_i\).

  • La variable objeto de estudio (“variable dependiente”) se representa como \(y_i\).

Una característica que distingue las series temporales es su orden cronológico. Esta circunstancia determina, además, que los datos de una serie temporal experimenten autocorrelación. Por ejemplo, la tasa de paro de un trimestre suele depender de la tasa del trimestre anterior.

Los objetivos del análisis de una serie temporal son los siguientes:

  • Comprender cómo ha evolucionado un proceso en el pasado (y de paso, los mecanismos que regulan su comportamiento en el tiempo).

  • Preveer valores futuros.

Para la realización de las actividades de este tema el script puede descargarse aquí

1.2 Tratamiento de series temporales en R

R trabaja con objetos pertenecientes a la clase ts (time series). La función ts() convierte un objeto (vector o dataframe) en una serie temporal; si no informamos de otra cosa, el primer caso del objeto corresponderá a \(t_1\), el segundo a \(t_2\) etc… La construcción de objetos de la clase ts requiere que los datos de partida estén distribuidos regularmente en la escala temporal utilizada.

La práctica se inicia importando los datos, que está en formato excel, desde la página web “https://personales.unican.es/rasillad/docencia/G14/TEMA_4”. Primero debe activarse el paquete readxl para acceder a los datos en formato excel.

#if(!require("readxl")) install.packages("readxl")
library(readxl)

A continuación se establece el vínculo con el servidor de los datos, que importará el fichero en la carpeta que esté activada por defecto con el nombre que deseemos (argumento destfile)

url<-"https://personales.unican.es/rasillad/docencia/G14/TEMA_4/series_temporales.xlsx"
download.file(url,
              destfile = "ejemplos_series_temporales.xlsx",
              mod="wb")

La primera serie aparece en la hoja de cálculo “ejemplo1”.

ejemplo1 <- read_excel("ejemplos_series_temporales.xlsx", 
                       sheet = "ejemplo1")
ejemplo1

Consiste en la duración en años del reinado de una serie de monarcas en sucesión consecutiva. El procedimiento se inicia transformando el vector original en una serie temporal (objeto ts).

reyes.ts <- ts(ejemplo1$reyes)                                              
reyes.ts

Además, podemos comprobar esa sucesión representando gráficamente esta serie temporal con la función plot.ts,

plot.ts(reyes.ts,                        
        col = 'darkgreen', 
        lwd = 1.5)       

La segunda serie es algo más compleja, ya que contiene el número mensual de nacimientos en España desde enero de 1946.

nacimientos <- read_excel("ejemplo.xlsx", 
                          sheet = "ejemplo2")
head(nacimientos)

En este caso, se puede incorporar información sobre el periodo temporal del que existen datos con dos argumentos:

  • frecuency: una serie mensual corresponde a una frecuencia de 12 meses.

  • start: fecha (año y mes) de comienzo de la serie.

nacimientos.ts <- ts(nacimientos,                             
               frequency=12,                                  
               start=c(1946,1))                               

R dispone de diferentes argumentos para caracterizar cualquier serie temporal:

class(nacimientos.ts)                                         # Confirma el tipo de serie ts
start(nacimientos.ts)                                         # Comienzo de la serie
end(nacimientos.ts)                                           # Final de la serie
frequency(nacimientos.ts)                                     # Periodicidad de la serie
time(nacimientos.ts)                                          # Vector con los intervalos temporales
cycle(nacimientos.ts)                                         # Unidad de tiempo a la que pertenece cada observación
print(nacimientos.ts)

Finalmente, se puede representar gráficamente.

plot.ts(nacimientos.ts, 
        col = 'brown', 
        lwd = 1.5, 
        xlab = "Años")
# setwd("")
url<-"https://personales.unican.es/rasillad/docencia/G14/TEMA_4/series_temporales_2.xlsx"
download.file(url,
              destfile = "series_temporales_2.xlsx",
              mod="wb")
  • Importa la variable temperatura como serie temporal (hoja de cálculo temperatura) y represéntala gráficamente.
df_temperatura <- read_excel("series_temporales_2.xlsx",
                          sheet = "Temperatura")
min_temperatura <- min(df_temperatura$año)
temperatura_ts <- ts(df_temperatura$tem,                            
                     frequency=1,                                  
                     start=c(min(df_temperatura$año),1))
plot.ts(temperatura_ts,
        col = 'brown',
        lwd = 1.5,
        xlab = "Años",
        ylab = "ºC",
        las = 1,
        main = "Temperatura media del planeta",
        ylim = c(13, 16))
  • Importa las variables SUP_ARB, SUP_NO_ARB e INCENDIOS como series temporales (hoja de cálculo Incendios) y represéntalas gráficamente en un mismo lienzo.
df_incendios <- read_excel("series_temporales_2.xlsx",
                        sheet = "Incendios")

min_incendios <- min(df_incendios$AÑO)

sup_arb_ts <- ts(df_incendios$SUP_ARB,                            
                     frequency=1,                                  
                     start=c(min(df_incendios$AÑO),1))

sup_no_arb_ts <- ts(df_incendios$SUP_NO_ARB,                            
                 frequency=1,                                  
                 start=c(min(df_incendios$AÑO),1))

incendios_ts <- ts(df_incendios$INCENDIOS,                            
                    frequency=1,                                  
                    start=c(min(df_incendios$AÑO),1))

plot.ts(sup_arb_ts,
        col = 'green',
        lwd = 1.5,
        xlab = "Años")

plot.ts(sup_no_arb_ts,
        col = 'darkgreen',
        lwd = 1.5)

ts.plot(sup_arb_ts,
        sup_no_arb_ts,
        gpars = list(col = c("black", "red")),
        xlab = "Años",
        ylab = "Hectáreas",
        main = "Evolución de la superficie quemada")

plot.ts(incendios_ts,
        col = 'darkgreen',
        lwd = 1.5)

2 ANÁLISIS DE UNA SERIE TEMPORAL.

Consiste en separar e identificar los diferentes componentes de una serie temporal. Los más habituales son:

Figura 1. Componente cíclica

Figura 2. Componente estacional

Figura 3. Componente aleatoria

De tal manera que una serie temporal puede encuadrarse en dos modelos según cómo se combinen estos componentes:

El tratamiento de una serie temporal depende de su naturaleza.

En este tema, nos centramos en datos temporales denominados de baja frecuencia (series anuales, trimestrales y mensuales), y se aplicarán procedimientos estadísticos para cuantificar, si existe, la tendencia, y aislar el comportamiento estacional. Otros aspectos, especialmente los ligados al análisis de las observaciones de alta frecuencia (diarias, horarias etc), que son mucho más complejos, serán omitidos.

2.1 Tendencia

La tendencia es el componente más relevante de cualquier serie temporal. En función de si presenta esta componente o no, es posible diferenciar dos tipos de series temporales:

2.1.1 Series estacionarias.

Son aquellas en las que sus propiedades estadísticas (fundamentalmente su valor medio y su dispersión) son estables, es decir, no varían con el tiempo. Si una serie temporal tiene una media constante a lo largo del tiempo, es estacionaria con respecto a la media. Si tiene varianza constante con respecto al tiempo, es estacionaria en varianza.

¿Qué tienen de bueno las series estacionarias?: como sus propiedades estadísticas son constantes, podemos estimarlas fácilmente y predecir una nueva observación.

Figura 4: serie estacionaria

Un tipo especial de serie estacionaria es la serie denominada ruido blanco. Es una serie en la que ninguna observación influye sobre las siguientes, es decir, sus valores son totalmente independientes e idénticamente distribuidos a lo largo del tiempo con media cero e igual varianza en el tiempo.

Figura 5. Ruido blanco

2.1.2 Series no estacionarias

Son aquellas en las que su valor medio y su dispersión cambian a lo largo del tiempo, es decir, ambas propiedades pueden crecer o decrecer y no oscilan en torno a un valor constante.

2.1.3 Identificación de series estacionarias/no estacionarias con R.

De acuerdo con lo antes expuesto, las series pueden ser:

  • Serie aditiva: la variabilidad se mantiene en el tiempo.

  • Serie multiplicativa: La variabilidad cambia (aumenta o disminuye) con el tiempo.

Por lo tanto, el primer aspecto a determinar es si una series temporal tiene un comportamiento estacionario respecto a la media (es decir, si tiene tendencia) o respecto a la varianza..

2.1.3.1 Estacionaridad de la media (cálculo de la tendencia temporal)

Cuando analizarmos si una serie tiene un comportamiento estacionario, se analiza si la serie posee tendencia, es decir, si estká organizada. Esta tendencia consiste en un cambio a largo plazo de la media, lo que supone que la serie experimenta cierto grado de autocorrelación temporal, es decir, que el valor observado en un tiempo \(y_1\) condiciona, creciendo o decreciendo, el valor alcanzado en el tiempo \(y_2\) y sucesivamente.

Esta tendencia puede ser:

  • Lineal. El valor promedio crece o decrece de manera constante, pero siempre en la misma dirección.

Figura 6. Tendencia lineal

  • Estocástica. El valor medio cambia, pero no de manera constante, sino en fases (cambios bruscos de promedio) de estabilidad, caída brusca, estabilidad, con cambios tanto de dirección (incrementos o decrecimientos) como de magnitud (mayores o menores).

Figura 7. Tendencia estocástica

En este apartado se revisan una serie de pruebas para determinar si una serie es estacionaria, es decir, si está organizada, o sea, si tiene tendencia o no. Partiremos de las pruebas más sencillas hasta las más complejas

2.1.3.1.1 Pruebas de Von Newman y Bartels

Ejemplo manual de aplicación de la prueba de von Newmann

data <- c(2,4,5,7,9)
data.ts <- ts(data) 

Figura 8

numerador <- sum((diff(data.ts))^2)
denominador <- length(data.ts)-1

rho <- numerador/denominador
var <- var(data.ts)*(length(data.ts)-1)/length(data.ts)                         # Varianza

Cálculo del parámetro K. Si el resultado es próximo a 2 la serie sería aleatoria, en caso contrario estaría organizada (el caso presentado).

K <- rho/var
K
rm(denominador, K, numerador, rho, var, data, data.ts)

La prueba de Bartels es una versión mejorada de la de von Neumann, que utiliza los rangos (número de orden) de cada componente de una serie temporal. Su objetivo:

  • \(H_0\) (hipótesis nula): los elementos siguen un orden aleatorio (sin tendencia en los datos). Corresponde a un p-value mayor que algún nivel de significación (la opción más común α = 0.05).

  • \(H_A\) (hipótesis alternativa): los elementos están organizados (hay una tendencia estadísticamente significativa, que podría ser positiva o negativa) si el p-value es menor que α = 0.05.

if (!require("trend")) install.packages("trend")
library(trend)                                                                    
bartels.test(reyes.ts)                                                           
2.1.3.1.2 Coeficiente de correlación

También se puede someter una serie temporal a un análisis de correlación entre los valores de la variable (\(y_1\)) y el tiempo (\(t_1\)). Se recomienda el uso del coeficiente de correlación de Spearman, ya que las series temporales no suelen tener una distribución normal. Si la relación entre ambas variables es signficativa (p-value) se considera que existe una tendencia significativa

cor.test(reyes.ts,                                     # Variable y: la serie temporal a analizar
    time(reyes.ts),                                    # Variable x: el periodo temporal a analizar
    method = "spearman")                              
2.1.3.1.3 Test de Mann kendall

Es una prueba no paramétrica, lo que significa que no se realiza ninguna suposición subyacente sobre la normalidad de los datos. Las hipótesis para la prueba son las siguientes:

  • \(H_0\) (hipótesis nula): no hay una tendencia en los datos. Corresponde a un p-value mayor que algún nivel de significación (la opción más común α = 0.05).

  • \(H_A\) (hipótesis alternativa): hay una tendencia estadísticamente significativa (que podría ser positiva o negativa) si el p-value es menor que α = 0.05.

Para realizar la prueba, se usa la función MannKendall() del paquete Kendall, a través de la siguiente sintaxis:

if(!require("Kendall")) install.packages("Kendall")
library(Kendall)
mk.reyes.ts <- MannKendall(reyes.ts)
summary(mk.reyes.ts)

El estadístico de prueba es 0.301 y el p-value correspondiente es 0.027486 . Debido a que este p-value es menor que 0.05, rechazaremos la hipótesis nula de la prueba y concluiremos que existe una tendencia en los datos.

  • Aplica las pruebas de Bartels y Mann-Kendall a las series temporales temperatura, SUP_ARB, SUP_NO_ARB e INCENDIOS y compara la significación de las tendencias obtenidas con las calculadas aplicando la correlación de Spearman.
bartels.test(temperatura.ts)
MannKendall(temperatura.ts)
cor.test(temperatura.ts,                                    
         time(temperatura.ts),                                
         method = "spearman")

bartels.test(sup_arb_ts)
MannKendall(sup_arb_ts)
cor.test(sup_arb_ts,                                    
         time(sup_arb_ts),                            
         method = "spearman")


bartels.test(sup_no_arb_ts)
MannKendall(sup_no_arb_ts)
cor.test(sup_no_arb_ts,                                  
         time(sup_no_arb_ts),                            
         method = "spearman")


bartels.test(incendios_ts)
MannKendall(incendios_ts)
cor.test(incendios_ts,                                  
         time(incendios_ts),                            
         method = "spearman")

2.1.3.2 Cuantificación de la tendencia

2.1.3.2.1 CASO 1 (tendencia determinista): Modelo de regresión lineal por el método de mínimos cuadrados

Para la obtención de la tendencia lineal mediante un modelo de regresión, debe considerarse variable dependente a \(y_n\) (en el ejemplo la duración del reinado en años) y variable independiente al tiempo \(t_n\).

modelo.regresion.reyes.ts <- lm(reyes.ts~time(reyes.ts))

La pendiente (término a) equivale a la tendencia (valor/unidad de tiempo). Los valores ajustados (predichos) corresponden a la evolución a largo plazo de la tendencia (línea recta).

modelo.regresion.reyes.ts$coefficients                                         
modelo.regresion.reyes.ts$fitted.values                                        

Esta tendencia a largo plazo puede representarse gráficamente

ts.plot(reyes.ts,
        xlab="Periodo temporal ",
        ylab="Duración del reinado",
        main= "Evolución del reinado")
points(reyes.ts)                                                                 
abline(modelo.regresion.reyes.ts)                                              # Dibuja la recta con la tendencia

Los resíduos son los valores que resultan una vez eliminada la tendencia. Podemos representarlos gráficamente también

ts.plot(modelo.regresion.reyes.ts$residuals)

2.1.4 CASO 2 (tendencia determinista): método de Sen

Este procedimiento se utiliza para descubrir tendencias en series temporales, pero es más resistente a valores atípicos, y no es paramétrico, ya que no se basa en ninguna distribución de probabilidad en particular. El método, descrito por primera vez por Theil y luego ampliado por Sen (1968), se denomina estimador de Thiel-Sen. Es una alternativa a la regresión por mínimos cuadrados, pero mientras este último método usa la media para estimar la pendiente, Sen usa la mediana.

El cálculo de la pendiente de la recta se realiza mediante dos pasos:

  • Calcular pendientes para todos los pares de puntos de tiempo ordenados.

  • Encuentra la mediana de todas las pendientes obtenidas en el procedimiento anterior.

Este procedimiento está incorporado en el paquete trend y su sintaxis es la siguiente:

sens.slope(x, conf.level = 0.95)

Donde:

  • x = vector numérico o un objeto de serie temporal de clase “ts”,

  • conf.level = nivel de significancia numérica .

if(!require("trend")) install.packages("trend")
library(trend)
sens.slope(reyes.ts,conf.level = 0.95)

Al igual que en los otros procedimientos, se puede solicitar la impresión en pantalla del valor de la tendencia ($estimate) y el p-valuede esa tendencia.

sens.slope(reyes.ts)$estimate
sens.slope(reyes.ts)$p.value

Sin embargo, el paquete trend no genera el término b (origen de la línea de regresión). Para obtenerlo necesitamos acudir a otro paquete, denominado zyp.

if (!require("zyp")) install.packages("zyp")
library(zyp)                                                            

Para que este procedimiento funcione, es necesario crear un vector con las unidades de tiempo.

tiempo <- seq(1, 42, length=42)                         #  Creación de una variable denominada tiempo
zyp.sen(reyes.ts~tiempo)                                # Cálculo de la pendiente según el método de Sen

Al igual que en el caso anterior, se puede requerir los términos a y b de la línea de regresión y los resíduos.

zyp.sen(reyes.ts~tiempo)$coefficients                   # Términos a y b
zyp.sen(reyes.ts~tiempo)$residuals                      # Los resíduos son los valores que resultan una vez eliminada la tendencia

ts.plot(zyp.sen(reyes.ts~tiempo)$residuals)

Finalmente, se puede calcular una tendencia lineal con eliminación previa de la autocorrelación temporal (prewhitened linear trend)

zyp.trend.vector(reyes.ts)

Si se desea obtener el valor de la tendencia (linear) mediante la expresión zyp.trend.vector(reyes.ts)$linear se obtiene un mensaje de error. Este error ocurre cuando se intenta acceder a un elemento de un vector atómico. Un “vector atómico” es cualquier objeto de datos unidimensional creado mediante las funciones c() o vector() en R. En su lugar, deben usarse corchetes dobles [[]] o la función getElement().

zyp.trend.vector(reyes.ts)[['linear']]

Desafío. Compara la tendencia obtenida aplicando un procedimiento de regresión lineal y el método de Sen a las series temporales temperatura, SUP_ARB, SUP_NO_ARB e INCENDIOS.

## Regresión lineal
modelo.regresion.temperatura_ts <- lm(temperatura.ts~time(temperatura.ts))
modelo.regresion.temperatura_ts$coefficients                                        

modelo.regresion.sup_arb_ts <- lm(sup_arb_ts~time(sup_arb_ts))
modelo.regresion.sup_arb_ts$coefficients                                        

modelo.regresion.sup_no_arb_ts <- lm(sup_no_arb_ts~time(sup_no_arb_ts))
modelo.regresion.sup_no_arb_ts$coefficients  

modelo.regresion.incendios_ts <- lm(incendios_ts~time(incendios_ts))
modelo.regresion.incendios_ts$coefficients  


## Método de Sen
sens.slope(temperatura.ts)$estimate
sens.slope(sup_arb_ts)$estimate
sens.slope(sup_no_arb_ts)$estimate
sens.slope(incendios_ts)$estimate

ts.plot(incendios_ts,
        xlab="Periodo temporal ",
        ylab="Número",
        main= "Evolución del número de incendios")

2.2 CASO 2: TENDENCIA EVOLUTIVA

En este caso, la evolución de \(T_t\) es una curva que cambia progresivamente. Como ventajas con respecto al cálculo de las tendencias realizadas con los métodos precedentes, el análisis de la tendencia evolutiva permite conocer el analizar el comportamiento pasado, detectar “fases” de crecimiento rápido o suave y desviaciones ocasionales por encima o por debajo de la tendencia, suavizando las fluctuaciones. Sin embargo, no podemos calcular valores futuros.

Antes de proceder al cálculo de las medias móviles, debe analizarse dónde se producen los puntos de cambio de esa serie temporal.

2.2.1 Test de Pettitt’s (definir puntos de cambio en una serie temporal)

Esta prueba se suele aplicar para detectar un punto de cambio en series temporales. Verifica si se cumple H0: la variable sigue una o más distribuciones que tienen el mismo parámetro de localización (es decir, no hay cambio), frente a HA, en la que existe un punto de cambio.

pettitt.test(reyes.ts)                             # Puntos de cambio: cuando el valor de una serie temporal cambia bruscamente
reyes.ts[22]
pettitt.test(reyes.ts)$statistic                                                 # K máximo, valor absoluto del estadístico U
pettitt.test(reyes.ts)$estimate                                                  # Probable punto de cambio
pettitt.test(reyes.ts)$p.value                                                   # the p-value del test

2.2.2 Cálculo de medias móviles

Una media móvil representa el valor promedio de una variable durante un periodo de tiempo, que se calcula de manera sucesiva.

Figura 9

La forma más fácil de calcular un promedio móvil en R es usar la función rollmean() del paquete zoo, que requiere requiere el parámetro k, que es el paso o duración del número de años sobre los que se calcula la media móvil (el denominador de la ecuación inferior).

if (!require("zoo")) install.packages("zoo")
library(zoo)

media_movil <- rollmean(reyes.ts, 
                        k = 13, 
                        fill = NA)
ts.plot(reyes.ts,
        xlab="Reinado",
        ylab="Duración en años",
        main= "Duración de los reinados de reyes ingleses")

points(reyes.ts)

lines(media_movil,
      col="black",
      lwd=4)

Hay diferentes tipos de filtros para suavizar una serie temporal. Un filtro loess es un método no paramétrico, por lo que, a diferencia de las medias móviles, dependemos menos de la elección del paso (nivel de suavidad). .

plot(reyes.ts)                                                                   # Dibuja los datos
lines(lowess(time(reyes.ts),reyes.ts),                                            # Suaviza la línea 
      col='blue')                                                               

Otro procedimiento para eliminar la tendencia es diferenciar una serie (es decir, calcular la diferencia entre una observación y su anterior).

x <- log(reyes.ts)
dif.x = diff(x)
plot(dif.x)

Desafío. A partir de la serie temporal de temperatura global:

  • Aplica el test de Pettit para conocer si existen puntos de cambio significativos.
pettitt.test(temperatura.ts)                             # Puntos de cambio: cuando el valor de una serie temporal cambia bruscamente

df.temperatura[pettitt.test(temperatura.ts)$estimate, ]
  • calcula sobre ella una media móvil de 11 términos y prepreséntala gráficamente.
tem_mm_11 <- rollmean(temperatura.ts,
                           k = 11,
                           fill = NA)
ts.plot(temperatura.ts,
        xlab="Reinado",
        ylab="Duración en años",
        main= "Duración de los reinados de reyes ingleses")
lines(tem_mm_11,
      col="black",
      lwd=4)
  • Diferencia la serie de temperaturas de un año a otro.
log_tem <- log(temperatura.ts)
dif_log_tem = diff(log_tem)
plot(dif_log_tem)

2.2.2.1 Estacionaridad de la varianza

Además de variaciones a largo plazo del valor medio de una serie temporal, también debe analizarse si existen variaciones en las fluctuaciones de esa serie temporal, es decir, cambios en la variabilidad a largo plazo.

Volvamos al caso de los nacimientos. Para ver si la varianza se ha modificado a lo largo del tiempo, agregaremos para cada año (al utilizar el argumento freq = 12 R calcula cada 12 eventos) el valor de la varianza

varianza.nacimientos <- aggregate(nacimientos.ts,         
                                  FUN = var)                        # Función varianza
plot(varianza.nacimientos)

Podemos realizar el mismo cálculo para el consumo de gas mensual en España entre 1966 y 1980.

ejemplo3 <- read_excel("ejemplo.xlsx", sheet = "ejemplo3")
gas.ts <- ts(ejemplo3$gas,
             frequency=12,                                  
               start=c(1966,1))
varianza.gas <- aggregate(gas.ts, 
                          FUN = var)
plot(varianza.gas)

A partir de este análisis, se comprueba que la variable gas.ts no es estacionaria, ya que, si bien presenta una tendencia aparentemente lineal, la amplitud de las fluctuaciones estacionales aumenta con el tiempo: su variabilidad no es constante. Muchos métodos de tratamiento de series temporales están diseñados para trabajar con series estacionarias (sin tendencia ni estacionalidad y con variabilidad constante). En caso contrario, se debe transformar la serie original estabilizando su varianza mediante varios procedimientos.

Uno de ellos es la transformación de los valores de la serie original en su logarítmo. Esta transformación funciona bien cuando la variabilidad es aproximadamente proporcional al nivel de la serie.

plot(log(gas.ts))

3 SERIE CON COMPORTAMIENTO ESTACIONAL

Un aspecto importante del análisis de una serie temporal es determinar si puede existir un comportamiento estacional dentro de esa serie. El comportamiento estacional consiste en cambios periódicos que se repiten con una frecuencia regular. Ejemplo de fenómenos con este tipo de comportamiento son:

¿Cómo podemos determinar si una serie ofrece un comportamiento estacional? A continuación se analiza el consumo de gas mensual en España desde 1966. Por ejemplo, dibujando un gráfico de caja y bigotes

boxplot(gas.ts ~ cycle(gas.ts))               

Pare existir un ligero componente estacional, con máximos en verano. Se puede avanzar en este aspecto calculando la ratio que supone cada mes con respecto al total anual. Para ello, con la función window() se extraerá un subconjunto de la serie temporal; si se acompaña del argumento freq = TRUE se extrae un subconjunto entre el comienzo y fin con un intervalo igual a su frecuencia

gas.ene <- window(gas.ts, start = c(1966,1), freq = TRUE)
gas.feb <- window(gas.ts, start = c(1966,2), freq = TRUE)
gas.mar <- window(gas.ts, start = c(1966,3), freq = TRUE)
gas.abr <- window(gas.ts, start = c(1966,4), freq = TRUE)
gas.may <- window(gas.ts, start = c(1966,5), freq = TRUE)
gas.jun <- window(gas.ts, start = c(1966,6), freq = TRUE)
gas.jul <- window(gas.ts, start = c(1966,7), freq = TRUE)
gas.ago <- window(gas.ts, start = c(1966,8), freq = TRUE)
gas.sep <- window(gas.ts, start = c(1966,9), freq = TRUE)
gas.oct <- window(gas.ts, start = c(1966,10), freq = TRUE)
gas.nov <- window(gas.ts, start = c(1966,11), freq = TRUE)
gas.dic <- window(gas.ts, start = c(1966,12), freq = TRUE)

Creamos nuevos vectores calculando el ratio de cada uno de los meses con respecto al total anual

gas.ene.ratio <- mean(gas.ene) / mean(gas.ts)
gas.feb.ratio <- mean(gas.feb) / mean(gas.ts)
gas.mar.ratio <- mean(gas.mar) / mean(gas.ts)
gas.abr.ratio <- mean(gas.abr) / mean(gas.ts)
gas.may.ratio <- mean(gas.may) / mean(gas.ts)
gas.jun.ratio <- mean(gas.jun) / mean(gas.ts)
gas.jul.ratio <- mean(gas.jul) / mean(gas.ts)
gas.ago.ratio <- mean(gas.ago) / mean(gas.ts)
gas.sep.ratio <- mean(gas.sep) / mean(gas.ts)
gas.oct.ratio <- mean(gas.oct) / mean(gas.ts)
gas.nov.ratio <- mean(gas.nov) / mean(gas.ts)
gas.dic.ratio <- mean(gas.dic) / mean(gas.ts)

Finalmente, se creará una tabla con esos ratios para verificar si existe ese comportamiento estacional.

ratios.mensuales.gas <- rbind(gas.ene.ratio,gas.feb.ratio,gas.mar.ratio,gas.abr.ratio,gas.may.ratio,gas.jun.ratio,
                              gas.jul.ratio,gas.ago.ratio,gas.sep.ratio,gas.oct.ratio,gas.nov.ratio,gas.dic.ratio)

ratios.mensuales.gas
rm(gas.ene,gas.feb,gas.mar,gas.abr,gas.may,gas.jun,
   gas.jul,gas.ago,gas.sep,gas.oct,gas.nov,gas.dic)
rm(gas.ene.ratio,gas.feb.ratio,gas.mar.ratio,gas.abr.ratio,gas.may.ratio,gas.jun.ratio,
      gas.jul.ratio,gas.ago.ratio,gas.sep.ratio,gas.oct.ratio,gas.nov.ratio,gas.dic.ratio)

Podemos a su vez eliminar la estacionalidad mediante el cálculo de la serie mensual de diferencias estacionales de orden 12.

diff.gas.ts <- diff(gas.ts, 
                     lag=12)
plot(diff.gas.ts)

Con la serie transformada podemos calcular el correlograma, una representación de las autocorrelaciones

autocorrelograma <- diff.gas.ts
acf(autocorrelograma)

acf(autocorrelograma, plot=FALSE)$acf                      # Valores numéricos de las correlaciones estimadas escribimos

Hay una versión de la prueba de Sen que tiene en cuenta el posible efecto de la estacionalidad.

sea.sens.slope(gas.ts)                                                        # Versíon que tiene en cuenta la estacionalidad

Hay una versión de la prueba de Sen que tiene en cuenta el posible efecto de la estacionalidad.

SeasonalMannKendall(gas.ts)

4 EXTRACCIÓN DE LA TENDENCIA, ESTACIONALIDAD Y FLUCTUACIONES ALEATORIAS CON LA FUNCIÓN decompose()

La función R “decompose”, obtiene las componentes de tendencia, estacionalidad e irregular de una serie temporal a través de medias móviles, y además permite obtener los componentes en base a un esquema aditivo ó multiplicativo. Es una función generica de R, lo que significa que no requiere de la instalación de ninguna librería. Su uso es el siguiente:

decompose(x, type = c(“additive”, “multiplicative”), filter = NULL)

Para una correcta descomposición de una serie temporal, es importante distinguir entre modelos multiplicativos y modelos aditivos. En esencia:

Como hemos visto anteriormente, se puede establecer el tipo de modelo analizando cómo ha evolucionado la varianza en el tiempo

Figura 10. Series temporales aditivas y multiplicativas

Este apartado se inicia con el análisis de los datos de nacimientos. Es una serie temporal aditiva, ya que no muestra cambios en la varianza a lo largo del tiempo. La función R “decompose” calcula de manera automática la tendencia y el componente estacional

nacimientos.descompuesta <- decompose(nacimientos.ts, "additive")               

tendencia.descompuesta.nacimientos <- ts(nacimientos.descompuesta$trend)      # Tendencia
componente.estacional.nacimientos <- ts(nacimientos.descompuesta$seasonal)    # Comportamiento estacional
componente.aleatoria.nacimientos <- ts(nacimientos.descompuesta$random)       # Residuos (sin tendencia ni comportamiento estacional

Es posible obtener en un único panel los gráficos correspondientes a esos componentes de la serie original

plot(nacimientos.descompuesta)                                    # Dibuja la serie estacional y los 3 componentes

También es posible dibujar cada componente de manera aislada.

plot(as.ts(nacimientos.descompuesta$trend))                                     # Dibuja sólo la tendencia
plot(as.ts(nacimientos.descompuesta$seasonal))                                  # Dibuja sólo la componente estacional
plot(as.ts(nacimientos.descompuesta$random))                                    # Dibuja sólo la componente aleatoria

Otra manera de calcular los valores de la componente aleatoria una vez eliminada la tendencia y la componente estacional

nacimientos.componente.aleatoria <- nacimientos.ts - (nacimientos.descompuesta$seasonal + nacimientos.descompuesta$trend)
plot(as.ts(nacimientos.componente.aleatoria))

Los datos obtenidos de la función decompose() pueden ser sometidos a procedimientos adicionales, como los vistos anteriormente. Por ejemplo, podemos calcular el coeficiente de correlación de Spearman para establecer la significación de la tendencia.

cor.test(nacimientos.descompuesta$trend,
         time(nacimientos.ts),        
         method = "spearman")   
plot(as.ts(nacimientos.descompuesta$trend))                                     
pettitt.test(na.omit(nacimientos.descompuesta$trend))
na.omit(nacimientos.descompuesta$trend)[78]
rm(list=ls())

Desafío. - Importa el fichero series_temporales_2.xlsx, que contiene las variables hn (banquisa del hemisferio N) y hs (banquisa del hemisferio S) como series temporales (hoja de cálculo banquisa).

df.banquisa <- read_excel("TEMA_4/series_temporales_2.xlsx",
                           sheet = "Banquisa")

hn.ts <- ts(df.banquisa$hn,                            
           frequency=12,                                  
           start=c(1978,11))                              

hs.ts <- ts(df.banquisa$hs,                            
            frequency=12,                                  
            start=c(1978,11))                              

par(mfrow=c(1,2))
plot(hn.ts)
plot(hs.ts)

par(mfrow=c(1,1))

boxplot(hn.ts ~ cycle(hn.ts))              
boxplot(hs.ts ~ cycle(hs.ts))              

hn.ts.descompuesta <- decompose(hn.ts, "additive")              
plot(hn.ts.descompuesta)
cor.test(hn.ts.descompuesta$trend,
         time(hn.ts),        
         method = "spearman")  
SeasonalMannKendall(hn.ts)
sea.sens.slope(hn.ts)                                  # Versión que tiene en cuenta la estacionalidad


hs.ts.descompuesta <- decompose(hs.ts, "additive")              
plot(hs.ts.descompuesta)
cor.test(hs.ts.descompuesta$trend,
         time(hs.ts),        
         method = "spearman")  
SeasonalMannKendall(hs.ts)
sea.sens.slope(hs.ts)                                 # Versión que tiene en cuenta la estacionalidad

5 NÚMEROS ÍNDICES

Un número índice se utiliza para medir los cambios en la magnitud de una variable o grupo de variables con respecto al tiempo. Permiten estudiar las variaciones en el tiempo de una o varias magnitudes de manera conjunta, independientemente de las unidades originales en las que esté medida cada magnitud.

¿Cuál es su utilidad:

Podemos clasificar todos estos índices en tres tipos:

Cuando usamos los números índice para comparar precios o cantidades de un solo producto, llamamos a estos números índice números índice simples. En ocasiones, puede ser necesario comparar los cambios en los precios o cantidades de muchos productos básicos, y estos precios o cantidades pueden estar en diferentes unidades. Los números índice construidos para este caso se denominan números índice agregados. Por lo tanto, tenemos dos métodos para construir números índice:

Existen varios tipos:

Existen diferentes paquetes estadísticos para el cálculo de números índice. En este caso, se ha elegido el paquete IndexNumber, ya que contiene diferentes funciones para el cálculo de números índices.

if (!require("IndexNumber")) install.packages("IndexNumber")
library(IndexNumber)

5.1 Números índices simples.

Los números índice simples se calcula sobre los valores de una sola magnitud. Pueden distinguirse a su vez dos subtipos, en función del modO de cálculo del periodo de referencia, también conocido como periodo base (\(y_{i0}\)).

En los números índice simples este periodo de referencia es único, anque puede situarse en cualquier punto de la serie temporal (el primer valor, el último o uno intermedio). A este periodo base se le asigna el valor 100; los restantes momentos en el tiempo se calculan como porcentajes respecto al valor de referencia según la siguiente función:

Figura 11. Fórmula del cálculo del periodo base

Figura 12. Fórmula del cálculo del periodo base

v1 <- c(70,75,77,77,85,90)

Cálculo de un índice simple

indice_simple <- index.number.serie(v1,                            # Vector o dataframe del que se toman los datos.
                                    "v1",                          # Nombre de la variable a calcular
                                    opt.plot=TRUE,                 # TRUE dibuja un gráfico con la evolución del índice.
                                    opt.summary=TRUE)              # TRUE proporciona un resumen estadístico de la variable

indice_simple$Summary                                              # Resumen estadístico
indice_simple$Index                                                # Valores del índice

nuevo.indice.simple <- as.data.frame(indice_simple$Index)          # Conversión en dataframe

La elección de este periodo base es importante, ya que su valor es anómalo tendría una repercusión negativa en los restantes valores del índice calculado. Por eso, es conveniente que sea un valor lo más “normal” posible. Una alternativa es el cálculo de los índices simples encadenados, en los que el periodo base no es único, sino que cambia con el tiempo, normalmente el intervalo temporal anterior.

Figura 13. Ejemplo de números índice encadenados

indice_encadenado <- index.number.chain(v1,                           # Vector conteniendo la magnitud 
                                        "v1",                         # Nombre de la variable estudiada
                                        opt.plot=TRUE,                # TRUE proporciona un gráfico
                                        opt.summary=TRUE)             # TRUE proporciona un resumen estadístico
nuevo.indice.encadenado <- as.data.frame(indice_encadenado$Index)

Desafío.

  • Crea las variables v2 y v3 (figura 12) y calcula sus respectivos índices simples y encadenados.
v2 <- c(10,12,16,20,25,22)
v2_indice_simple <- index.number.serie(v2,                            # Vector o dataframe del que se toman los datos.
                                    "v2",                          # Nombre de la variable a calcular
                                    opt.plot=TRUE,                 # TRUE dibuja un gráfico con la evolución del índice.
                                    opt.summary=TRUE)              # TRUE proporciona un resumen estadístico de la variable
v2_indice_encadenado <- index.number.chain(v2,                           # Vector conteniendo la magnitud
                                        "v2",                         # Nombre de la variable estudiada
                                        opt.plot=TRUE,                # TRUE proporciona un gráfico
                                        opt.summary=TRUE)             # TRUE proporciona un resumen estadístico
df_v2 <- cbind(v2, v2_indice_simple, v2_indice_encadenado)


v3 <- c(120,125,128,130,137,145)
v3_indice_simple <- index.number.serie(v3,            # Vector o dataframe del que se toman los datos.
                                    "v3",             # Nombre de la variable a calcular
                                    opt.plot=TRUE,    # TRUE dibuja un gráfico con la evolución del índice.
                                    opt.summary=TRUE)              # TRUE proporciona un resumen estadístico de la variable
v3_indice_encadenado <- index.number.chain(v3,                           # Vector conteniendo la magnitud
                                        "v3",                         # Nombre de la variable estudiada
                                        opt.plot=TRUE,                # TRUE proporciona un gráfico
                                        opt.summary=TRUE)             # TRUE proporciona un resumen estadístico
df_v3 <- cbind(v3, v3_indice_simple, v3_indice_encadenado)

5.2 Números índice complejos.

Sirven para estudiar la evolución conjunta de diferentes variables, en los que la importancia relativa de una de ellas es superior a las restantes (Figura 14). Una posible solución, la de promediar las diferentes series de números índices no sería efectiva, ya que no reflejaría la mayor importancia relativa de esa variable

Figura 14. Ejemplo de números índice simples promediados

Para solucionar este inconveniente se recurre a ponderar, es decir, a proporcionar un peso diferente a cada índice dependiendo de su importancia, según la siguiente fórmula:

Figura 15. Fórmula ponderaciones

donde \(w_i\) es el peso o ponderación que se asigna a cada variable.

precio <- matrix(c(1,2,5,15,1.2,1.9,4.8,16, 1.3,1.95,5.1,15.5), ncol = 3)
cantidad <- matrix(c(150,430,300,250, 140, 420, 350, 220, 180, 450, 360, 280), ncol = 3)

Para elaborar este tipo de índices existen diferentes métodos; los más conocidos son el método de Laspeyres, el método de Paasche y el método de Fisher.

5.2.1 Índice de Laspeyres

Este índice tiene la ventaja de requerir un menor número de variables y reflejar adecuadamente el peso de cada componente en el total. Su mayor inconveniente es que no contempla la evolución de las variables (puede que el peso de cada magnitud varíe durante el periodo de análisis).

Figura 16. Fórmula índice Laspeyres

laspeyres.index.number(precio,                        # 
                       cantidad,                      # 
                       "Precio",                      # Etiqueta de la variable
                       opt.plot=TRUE,
                       opt.summary=TRUE)

5.2.2 Índice de Paasche

Su mayor ventaja es que refleja posibles cambios temporales en las variables, pero requiere más datos.

Figura 17. Fórmula índice Laspeyres

paasche.index.number(precio,
                     cantidad,
                     "Resultado",
                     opt.plot=TRUE,
                     opt.summary=TRUE)

Desafío.

A partir de los siguientes datos: p <- c(11.31,11.22,11.64, 12.66, 13.68, 13.94, 14.79, 16.06, 8.20, 8.03, 8.03, 9.24) q <- c(1.270, 1.225,1.149,0.958, 0.068, 0.066, 0.048, 0.033, 3.829, 3.727, 3.365, 2.854)

  • Crea sendas matrices con 3 columnas.

  • Calcula el índice de Laspeyres

  • Calcula el índice de Paasche

ACTIVIDADES DE EVALUACIÓN CONTINUA

El fichero word 04_Actividad_evaluacion_continua_2023 contiene una serie de actividades encaminadas a poner en práctica los conocimientos adquiridos. Cada alumnos deberá elaborar un script que contenga los procedimientos necesarios para responder a las cuestiones planteadas, y enviarlo posteriormente al profesor a través de correo electrónico.