Carga de las librerias

El primer paso es cargar todas las librerias que vamos a necesitar para el analisís de la data de serie de tiempo que en este caso sería sobre la producción de banano en el Perú.

library(tidyverse)
library(timetk)
library(lubridate)
library(tidyquant)
library(ggthemes)
library(gghalves)
library(cowplot)
library(workflows)
library(tseries)
library(forecast)
library(kableExtra)
library(scales)
library(TSstudio)
library(quantmod)
library(prophet)
library(MLmetrics)

Analisís exploratorio de la data y carga

En este primer punto vamos a cargar y a vizualizar la data:

platano<-data.frame(
          produccion = c(147.371159,152.182556,160.790619,
                 157.293118,164.338878,158.463878,148.97636,143.624538,145.816277,
                 150.99869,150.163846,154.491132,151.758208,146.51327,
                 151.741334,150.074037,151.470145,149.906911,144.316301,
                 143.187392,146.158856,149.385473,154.719854,153.696405,150.376969,
                 154.888863,158.415161,159.722148,157.630174,154.815207,
                 149.056858,150.576067,151.947289,157.103518,161.39615,
                 160.659132,161.846129,166.674599,167.885732,165.936425,
                 168.286208,162.252202,162.080967,158.663838,164.9181,169.030185,
                 176.43621,183.273389,173.638657,165.984067,160.789995,
                 163.594556,162.707968,160.551264,158.092557,159.771377,
                 161.949449,163.192935,169.600112,168.177966,178.198947,173.610783,
                 168.867025,172.376671,174.436138,173.959957,171.630839,
                 168.938216,170.086631,174.341566,175.755489,179.887017,
                 177.91952,174.917211,173.731928,174.173227,175.739808,
                 177.224146,175.434206,175.035709,170.021068,176.444789,178.698977,
                 182.130758,180.56635,178.80341,178.328438,175.681238,
                 177.698589,177.523634,173.066538,170.90857,172.848798,
                 175.890558,182.518149,182.004675,176.102834,176.122108,178.600478,
                 169.434709,170.571144,166.899906,166.179164,165.824392,
                 174.193714,169.798257,165.662647,176.953489,178.135472,
                 176.454895,172.719461,170.726007,166.722298,164.785553,
                 168.611306,164.855188,171.553293,175.797751,180.438752,183.194697,
                 179.551176,169.845169,157.363035,158.037373,158.463398,
                 157.847198,154.879749,157.550217,168.212012,170.761465,
                 171.756231,176.780341,182.152581,181.32935,182.527638,179.486023,
                 183.22613,178.788919,180.015041,177.379192,183.302556,
                 182.370188,186.201489,198.097382,192.74546,196.863237,
                 192.465966,185.81338,187.157967,184.969185,183.16038,177.995692,
                 184.76729,182.483757,191.223727,192.525463,198.109822,
                 195.849999,191.929352,188.815842,191.924062,187.130535,
                 187.256134,183.448624,191.069038,196.060862,200.900889,202.01863,
                 194.693868,190.787659,188.302469,191.931834,187.938512,
                 189.701557,189.581945,189.668909,192.245874,196.0051252,
                 203.733493)
)
platano%>% head(10) %>% kbl() %>% kable_material_dark() %>%  
  column_spec(column = 1, width = "1cm", background = alpha("blue",0.3)) 
V1
147.3712
152.1826
160.7906
157.2931
164.3389
158.4639
148.9764
143.6245
145.8163
150.9987

Ahora el siguiente paso es realizar un analisís exploratio por lo que primero vamos a graficar a la serie.

Grafico de la serie temporal

Primero transformamos la data a clase ts.

platano<- ts(platano$produccion,start = c(2007),frequency = 12)
plot.ts(platano);title("Produccion de babano en el Peru")

Otra forma de mejorar el grafico es usando el paquete forecast ya que nos permite graficar de forma automatica la serie temporal en un formato de ggplo2.

autoplot(platano)+theme_minimal()+labs(title = "Produccion de babano en el Peru",
                                       x="tiempo")+geom_line(color="blue")

Ahora se puede observar una clara tendencia creciente en lo que respecta en la producción total del banano.

Descomposición de la serie temporal

Aquí veremos que la serie se puede descomponer en: tendencia, estacionalidad y el factor aleatorio.

ts_decompose(platano)

En el siguiente grafico iterativo se puede ver que la serie presenta un factor estacional por lo que indica que la serie puede ser modelada por un modelo SARIMA.

Comportameinto estacional

Ahora toca ver y anilizar el comportemiento estacional del banano para esto vamos a recurrir a varias funciones que nos generaran varios gráficos para nuestro analisís.

# En este paso obtenemos los primeros 12 valores de la seria en donde tomamos l factor estacional. 
# Son 12 debdio que en el componente estacional siemple se repite un patron.

estacional <- decompose(platano)$seasonal
factor<- estacional[1:12]

# Ahora se crea un dataframe en donde se toma dos culumnas una por los meses y la otra de los valores de 
# los factores

base_e <- data.frame("n"=1:12,"com"=factor)

# Ahora se crea el grafico 

base_e %>% ggplot(aes(n,com))+geom_col(fill=ifelse(factor>0,"blue","red"))+
  theme_minimal()+labs(title = "comportamiento estacional",
                       subtitle = "Producción de platano",
                       x="Meses",y=" ")+geom_hline(yintercept = 0,
                                                   color="black",size=0.8)+
  geom_line()+geom_point(color=ifelse(factor>0,"blue","red"),size=2)

Ahora se puede observar que la proudccion de platano es alta o tiene una temporada alta en los meses de enero y dicembre. Una temporada baja y en agosto se registra la mayor caída en la producción de este producto.

platano <- as.xts(platano)  
tiempo<- index(platano)
base <- data.frame("Fecha"=tiempo,"Produccion"=platano,anio=year(tiempo),
                   mes=month(tiempo))

base %>% head(5) %>% kbl() %>% kable_material_dark() %>%  
  column_spec(column = 1, width = "1cm", background = alpha("blue",0.3)) 
Fecha Produccion anio mes
Ene. 2007 Ene. 2007 147.3712 2007 1
Feb. 2007 Feb. 2007 152.1826 2007 2
Mar. 2007 Mar. 2007 160.7906 2007 3
Abr. 2007 Abr. 2007 157.2931 2007 4
May. 2007 May. 2007 164.3389 2007 5
base %>% 
  mutate(
    weekday = MONTH(Fecha, label = TRUE, abbr = FALSE), 
    weekday = weekday %>% as_factor() 
  ) %>% 
  ggplot(aes(x=weekday, y=Produccion)) +
  geom_jitter(aes(color=weekday),
              alpha = 0.5,
              size=0.5,
              show.legend = FALSE) + 
  geom_half_violin(aes(fill=weekday),
                   side = "l",
                   alpha = 0.45,
                   show.legend = FALSE,
                   trim = FALSE) +
  geom_half_boxplot(aes(fill = weekday),
                    side = "r",
                    outlier.size = 3,
                    outlier.color = "red",
                    width = 0.4, 
                    alpha = 0.45,
                    show.legend = FALSE) + 
  stat_summary(fun = median, geom="line")  +
  theme_bw() 

En este grafico refleja la distribución de cada mes en la producción de banano en donde como se dijo en el grafico anterior que el mes de enero y dicembre eran los mese en donde la producción era mayoy, en cambio en el mes de agsoto era la más baja.

otra forma de analizar esto en pocas lineas de codigo es de la siguiente manera:

base %>% as_tibble()-> ata
s<- ata %>% plot_seasonal_diagnostics(Fecha,Produccion,.interactive = T)

s

Modelamiento de la serie

Ahora se formularan los sigueintes modelos:

  • Arima
  • Red neuronal
  • Prophet
train <- platano %>% head(167)
test <- platano %>% tail(12)

Modelo ariam

Para esta ocasión se usara la función autoarima:

modelo1 <- auto.arima(train)
summary(modelo1)
Series: train 
ARIMA(1,1,0)(2,0,0)[12] with drift 

Coefficients:
          ar1    sar1    sar2   drift
      -0.0722  0.2355  0.2750  0.3400
s.e.   0.0798  0.0745  0.0788  0.5465

sigma^2 estimated as 17.23:  log likelihood=-471.39
AIC=952.78   AICc=953.16   BIC=968.34

Training set error measures:
                     ME     RMSE      MAE         MPE    MAPE      MASE
Training set 0.01343089 4.087931 3.176903 -0.02443785 1.86756 0.4600254
                    ACF1
Training set 0.001148116

Modelo red neuronal

modelo2 <- nnetar(train)
summary(modelo2)
          Length Class        Mode     
x         167    ts           numeric  
m           1    -none-       numeric  
p           1    -none-       numeric  
P           1    -none-       numeric  
scalex      2    -none-       list     
size        1    -none-       numeric  
subset    167    -none-       numeric  
model      20    nnetarmodels list     
nnetargs    0    -none-       list     
fitted    167    ts           numeric  
residuals 167    ts           numeric  
lags        2    -none-       numeric  
series      1    -none-       character
method      1    -none-       character
call        2    -none-       call     

Modelo prophet

df <- base %>% select(Fecha,Produccion)
names(df)<- c("ds","y")
modelo3 <- prophet(df)

Vamos a realizar la proyección y la comparación segun la data de test

pred1 <- forecast(modelo1,12)
pred2 <- forecast(modelo2,12)
futuro <- make_future_dataframe(modelo3, periods = 12)
pred3 <- predict(modelo3, futuro)
proy <- pred3[["yhat"]] %>% tail(12)
data_pred<- data.frame(n=1:12,sarima=pred1$mean,nnet=pred2$mean,prophet=proy,test=test)
data_pred %>% ggplot(aes(n,test)) + geom_line(aes(color="test")) + 
  geom_line(mapping = aes(x=n,y=sarima,color="sarima"))+ geom_line(mapping = aes(x=n,y=nnet,color="nnet"))+
   geom_line(mapping = aes(x=n,y=prophet,color="prophet"))

p <- c(RMSE(test,pred1$mean),MAPE(test,pred1$mean),RMSLE(test,pred1$mean))
p1 <- c(RMSE(test,pred2$mean),MAPE(test,pred2$mean),RMSLE(test,pred2$mean))
p2 <- c(RMSE(test,proy),MAPE(test,proy),RMSLE(test,proy))
dac <- cbind(p,p1,p2) %>% as.data.frame()
dac %>% kbl() %>% kable_material_dark() %>%  
  row_spec(2,  background = alpha("blue",0.3)) 
p p1 p2
10.3437583 4.7678873 26.7020321
0.0472539 0.0215391 0.1145659
0.0524057 0.0243884 0.1291831

El mejor modelo es nnet ya que posee un MAPE menor a todos

modelo2 <- nnetar(platano)
prednnet <- forecast(modelo2,12)
autoplot(prednnet)