Code
library(TSstudio)
library(zoo)
library(xts)
library(readxl)
library(tidyverse)
library(feasts)
library(fable)
library(timetk)
library(tsibble)
library(lubridate)
library(dygraphs)
library(MASS)

1 Exportaciones mensuales de Colombia

Code
#Gráfico dinámico con dygraphs
dygraph(exportaciones_ts,main="Serie de Exportaciones Mensuales en Colombia", ylab="Valor total de las exportaciones")%>% dyRangeSelector()
Code
#Obtener información del objeto de tipo ts
TSstudio::ts_info(exportaciones_ts)
 The exportaciones_ts series is a ts object with 1 variable and 282 observations
 Frequency: 12 
 Start time: 2000 1 
 End time: 2023 6 

La serie de tiempo de exportaciones de Colombia presnetada en el gráfico es una serie de tiempo mensual con frecuencia 12 con valores desde enero del 2000 hasta junio del 2023, sin ninguna observación faltante, o sea que cuenta con 282 observaciones. Del gráfico podemos suponer las siguientes características de la serie:

  • Varianza marginal: La serie pareciera tener varianza marginal no constante, pues su rango de valores resulta ser pequeño en ciertos periodos de tiempo y grande en otros. Por ejemplo, de noviembre de 2008 a febrero de 2011 hay un rango grande, de marzo de 2011 a octubre de 2014 hay un rango pequeño y de noviembre de 2014 a febrero de 2016 hay de nuevo un rango grande.

  • Tendencia: A simple vista la serie presenta una tendencia determinística lineal creciente en los primeros años de observación. Sin embargo, desde el año 2011 la serie no sigue el mismo patrón y su tendencia empieza a variar por periodos de tiempo, por lo que se puede pensar en una tendencia de tipo estocástico.

  • Componente Estacional: Haciendo una observación detallada de la serie acortando los años con ayuda del gráfico dinámico, se puede ver que la serie presenta picos en los meses de mayo y noviembre. Por los que se cree que hay existencia de estacionalidad de periodo 6 meses.

1.0.1 Estabilización de la Varianza

A continuación se evaluará si es necesario y conveniente hacer una tranformación de Box-Cox para estabilizar la varianza marginal de la serie.

Veremos primero qué valores del parámetro lambda de la transformación de Box-Cox nos maximiza la log-verosimilitud. Si estos valores están lejos de 1 se sugiere hacer una transformación de Box-Cox.

Code
MASS::boxcox(lm(exportaciones_ts ~ 1),seq(-1, 2, length = 500))

A patir de la gráfica anterior se verifica que los valores de lambda que maximizan la log-verosimilitud estan alrededor de 0.6, con un intervalo que no incluye al 1. Se toma la decisión de transformar la serie con lambda igual a \(0.6\) y se observam los resultados en comparación con la serie original.

Code
lexportaciones_ts <- (1/0.6)*((exportaciones_ts^(0.6))-1)
Code
par(mar = c(1,1,1,1))
par(mfrow=c(1,2))
dygraph(exportaciones_ts,main="Serie de Exportaciones Mensuales en Colombia", ylab="Valor total de las exportaciones")%>% dyRangeSelector()
Code
dygraph(lexportaciones_ts,main="Serie transformada con lambda=0.6", ylab="Valor")%>% dyRangeSelector()

Se nota un ligero cambio en la varianza marginal de la serie, en particular una disminución general de la varianza marginal. Se verifican los valores del parámetro lambda de la transforación de Box-Cox que maximizan la log-verosimilitud de la serie transformada.

Code
MASS::boxcox(lm(lexportaciones_ts ~ 1),seq(-1, 2, length = 500))

El valor de lambda que maximiza la log-verosimilitud sobre la serie transformada es ahora muy cercano a 1, por lo que se considera una buena transformación. Sin embargo, dado que el cambio no es muy notorio se toma la recomendación de ser flexibles con el valor de lambda y se realiza una transformación que es más notoria y que cumple con incluir al uno entre los valores de lambda que maximizan la verosimilitud.

El valor usado será lambda = 0.45, obteniendo los resultados siguientes

Code
lexportaciones_ts <- (1/0.45)*((exportaciones_ts^(0.45))-1)
Code
par(mar = c(1,1,1,1))
par(mfrow=c(2,1))
dygraph(exportaciones_ts,main="Serie de Exportaciones Mensuales en Colombia", ylab="Valor total de las exportaciones")%>% dyRangeSelector()
Code
dygraph(lexportaciones_ts,main="Serie transformada con lambda=0.45", ylab="Valor")%>% dyRangeSelector()
Code
MASS::boxcox(lm(lexportaciones_ts ~ 1),seq(-1, 5, length = 500))

Se decide continuar con esta última serie obtenida.

Code
#Otras opciones de transformación 
library(VGAM)
Loading required package: stats4
Loading required package: splines
Code
prueba<-VGAM::yeo.johnson(exportaciones_ts, lambda = 0.4)
Code
dygraph(prueba,main="Serie transformada con yeo.jhonson", ylab="Valor")%>% dyRangeSelector()

1.0.2 Análisis de Tendencia

Inicialmente revisaremos la función de autocorrelación, pues su forma nos dará indicios de si exisste tendencia o no.

Code
acf(lexportaciones_ts, 36, main = "ACF de la serie estabilizada")

La serie presenta alta autocorrelación de los rezagos con un decaimiento leve a medida que el rezago es mayor, estoo es un indicio de que la serie presenta tendencia. A continuación se realizaran ajustes determinísticos de la misma.

1.0.2.1 Ajuste determinístico lineal

Code
summary(fit <- lm(lexportaciones_ts~time(lexportaciones_ts), na.action=NULL))

Call:
lm(formula = lexportaciones_ts ~ time(lexportaciones_ts), na.action = NULL)

Residuals:
    Min      1Q  Median      3Q     Max 
-633.53 -195.39  -61.69  170.42  666.72 

Coefficients:
                          Estimate Std. Error t value Pr(>|t|)    
(Intercept)             -81496.270   4705.423  -17.32   <2e-16 ***
time(lexportaciones_ts)     41.382      2.339   17.69   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 266.5 on 280 degrees of freedom
Multiple R-squared:  0.5278,    Adjusted R-squared:  0.5261 
F-statistic:   313 on 1 and 280 DF,  p-value: < 0.00000000000000022
Code
plot(lexportaciones_ts, main= "Tendencia lineal ajustada")
abline(fit,col = "red")# Se añade la recta ajusta

1.0.2.2 Serie sin tendencia

Code
noTendlexportaciones_ts <- lexportaciones_ts - predict(fit)
plot(noTendlexportaciones_ts, main="Serie Sin tendencia", 
     ylab= "Valor")

Code
acf(noTendlexportaciones_ts,lag.max =length(noTendlexportaciones_ts), 
    main="ACF Serie Sin tendencia")

1.0.2.3 Ajuste por medio de filtro de promedios móviles

Code
descom_lexportaciones <- decompose(lexportaciones_ts)
plot(descom_lexportaciones)

Code
plot(lexportaciones_ts, ylab= "Valor en escala logarítmica")
abline(fit,col = "red")# Se añade la recta ajusta
points(time(lexportaciones_ts), descom_lexportaciones$trend, col ="green", cex=0.4)

La línea de tendencia ajustada po medio del filtro de promedios móviles es muy distinta a la línea de tendencia lineal ajustada. Veamos como queda la serie al eliminar la tendencia usando este ajuste.

Code
noTendlexportaciones_ts2 <- lexportaciones_ts - descom_lexportaciones$trend
plot(noTendlexportaciones_ts2, main="Serie Sin tendencia", 
     ylab= "Valor")

Se observa que esta estimación de la tendencia se ajusta mejor, pues al eliminar la tendencia la serie oscila constantemente alrededor de cero.

Sin embargo, a pesar que se estabilizó la varianza previamente, se sigue notando algo de varianza marginal no constante y de forma más notoria. Al inicio varinza baja y al final varianza alta.

Code
acf(noTendlexportaciones_ts2[7:276],lag.max =length(noTendlexportaciones_ts2), 
    main="ACF serie Sin tendencia")

Code
acf(noTendlexportaciones_ts2[7:276],lag.max =48, 
    main="ACF serie Sin tendencia")

2 Descomposición STL

Code
####Primera aproximación del ajuste STL
lexportaciones_tbl%>%timetk::plot_time_series(Fecha, lexportaciones, 
                   .interactive = TRUE,
                   .plotly_slider = TRUE)
Code
#####Ajuste STL

lexportaciones_ajus <- smooth_vec(lexportaciones,span = 0.75, degree = 2)
lexportaciones_tbl%>%dplyr::mutate(lexportaciones_ajus)
# A tibble: 282 × 3
   Fecha      lexportaciones lexportaciones_ajus
   <date>              <dbl>               <dbl>
 1 2000-01-01          1117.               1021.
 2 2000-02-01          1138.               1026.
 3 2000-03-01          1138.               1031.
 4 2000-04-01          1053.               1036.
 5 2000-05-01          1182.               1041.
 6 2000-06-01          1186.               1046.
 7 2000-07-01          1162.               1051.
 8 2000-08-01          1226.               1056.
 9 2000-09-01          1162.               1061.
10 2000-10-01          1102.               1067.
# ℹ 272 more rows
Code
###Ajuste STL moviendo los parámetros
lexportaciones_tbl%>%mutate(lexportaciones_ajus=smooth_vec(lexportaciones,span = 0.75, degree = 2))%>%
  ggplot(aes(Fecha, lexportaciones)) +
    geom_line() +
    geom_line(aes(y = lexportaciones_ajus), color = "red")

Se observa que el ajuste es mucho más suavizado.

Code
###Eliminamos la tendencia con la predicción la recta xts
noTendlexportaciones_ts3 <- lexportaciones_ts - lexportaciones_ajus
plot(noTendlexportaciones_ts3, main="Serie Sin tendencia", 
     ylab= "Valor en escala logarítmica") 

Code
acf(noTendlexportaciones_ts3,lag.max =length(noTendlexportaciones_ts3), 
    main="ACF serie Sin tendencia")

2.0.0.1 Serie Diferenciada

Code
###Diferenciando con base en el objeto ts
dlexportaciones<-diff(lexportaciones_ts)
plot(dlexportaciones)
abline(h=0, col = "red")

Al observar la serie diferenciada se hace más evidente la presencia de varianza marginal no constante en la serie, lo que quiere decir que las tansformación no la ha corregido lo suficiente.

Code
acf(dlexportaciones,lag.max =length(dlexportaciones), main="ACF de la Serie Diferenciada")

Code
acf(dlexportaciones,lag.max =100, main="ACF de la Serie Diferenciada")

Varios rezagos superan el umbral de autocorrelación, en especial los que se encuentran cerca a las unidades. Por lo que se cree que hay presencia de una componente estacional de periodo 12.

Dadas las anteriores estimaciones de la tendencia y analizando cada una de las series con dichas tendencias estimadas eliminadas, se opta por continuar el estudio de la serie sin la tendencia dada por el filtro de promedios móviles y con la serie con la tendencia eliminada por medio de la diferenciación de la serie.

2.0.1 Análisis de Estacionalidad

A continuación se busca determinar si la serie presenta una componente estacional con la ayuda de diversos métodos. Se aplican los métodos sobre las series que fueron elegidas en la sección anterior.

2.0.1.1 Correlación de las observaciones con sus retardos

Se observa que tan correlacionadas estan las observaciones con sus retardos desde el 1 hasta el 12. Primero los resultados con la serie obtenida al estimar la tendencia con filtro de promedios móviles.

Code
par(mar = c(3,2,3,2))
astsa::lag1.plot(noTendlexportaciones_ts2[7:276], 12,corr=T)

Las correlaciones negativas que más destacan son las de los rezagos 4, 5 y 6. Y las positivas que mas destacan son las de los rezagos 1 y 12.

Ahora veamos de la serie diferenciada:

Code
par(mar = c(3,2,3,2))
astsa::lag1.plot(dlexportaciones, 12,corr=T)

Las correlaciones negativas que destacan son las de los rezagos 1 y 6, y la positiva es la del rezago 12. Coinciden en ser correlaciones negativas las del rezago 6 para ambos casos y en ser correlaciones positivas las del rezago 12 en ambos casos. Por lo que se sospecha de un ciclo estacional anual.

2.0.1.2 Función de autocorrelación parcial

Code
#pacf
pacf(noTendlexportaciones_ts2[7:276], 100, main = "PACF Serie sin tendencia")

Code
#pacf
pacf(dlexportaciones, 100, main = "PACF Serie Diferenciada")

2.0.1.3 AMI

Sobre la serie ajustada por medio del filtro de promedios móviles

Code
tseriesChaos::mutual(noTendlexportaciones_ts2[7:276], partitions = 16, lag.max = 50, plot=TRUE)

Ahora veamos sobre la serie diferenciada:

Code
tseriesChaos::mutual(dlexportaciones, partitions = 16, lag.max = 50, plot=TRUE)

2.0.1.4 Mapas de calor

Con la serie sin tendencia:

Code
prueba<-xts(noTendlexportaciones_ts2[7:276],indice[7:276])

TSstudio::ts_heatmap(prueba, title = "Mapa de calor - Exportaciones sin tendencia")
Code
TSstudio::ts_heatmap(dlexportaciones, title = "Mapa de calor - Exportaciones sin tendencia")

2.0.1.5 Perdiodograma

Code
# periodograma
Periodograma <- spectrum(as.numeric(noTendlexportaciones_ts2[7:276]),log="no",span=c(5,5))

Code
ubicacionElim<- which.max(Periodograma$spec)
sprintf("El valor de la frecuencia donde se máximiza el periodograma para la serie es: %s",Periodograma$freq[ubicacionElim])
[1] "El valor de la frecuencia donde se máximiza el periodograma para la serie es: 0.0851851851851852"
Code
sprintf("El periodo correspondiente es aproximadamente: %s",1/Periodograma$freq[ubicacionElim])
[1] "El periodo correspondiente es aproximadamente: 11.7391304347826"
Code
# periodograma
Periodograma <- spectrum(as.numeric(dlexportaciones),log="no",span=c(5,5))

Code
ubicacionElim<- which.max(Periodograma$spec)
sprintf("El valor de la frecuencia donde se máximiza el periodograma para la serie es: %s",Periodograma$freq[ubicacionElim])
[1] "El valor de la frecuencia donde se máximiza el periodograma para la serie es: 0.416666666666667"
Code
sprintf("El periodo correspondiente es aproximadamente: %s",1/Periodograma$freq[ubicacionElim])
[1] "El periodo correspondiente es aproximadamente: 2.4"
Volver arriba