Colombia, como país en desarrollo, experimenta un crecimiento acelerado en sus principales ciudades, al tiempo que avanza en la interconexión de zonas anteriormente aisladas. Este proceso de expansión territorial y urbana impulsa un incremento constante en la demanda de energía a nivel nacional.
En este contexto, diversos analistas advierten sobre un posible déficit energético en los próximos años, derivado del aumento sostenido de la demanda, así como de los retrasos en la entrada en operación de nuevos proyectos de generación. Si bien el país ha dado pasos importantes hacia la diversificación de su matriz energética —con la implementación de granjas solares en distintas regiones y parques eólicos en La Guajira—, la generación eléctrica sigue dependiendo en gran medida de las centrales hidroeléctricas, que representan aproximadamente el 60% del total.
Esta alta dependencia de las fuentes hídricas constituye un riesgo estructural, especialmente ante fenómenos climáticos como El Niño, que generan sequías prolongadas y reducen drásticamente la capacidad de generación hidroeléctrica.
Ante este panorama, es crucial que los actores del sector energético adopten una visión prospectiva, anticipándose a los cambios en la demanda y fortaleciendo su capacidad de respuesta. La planeación basada en pronósticos confiables, junto con una gestión eficiente de riesgos y recursos financieros, será fundamental para evitar escenarios críticos como el racionamiento o apagones, y garantizar la sostenibilidad energética del país a mediano y largo plazo.
En este contexto, el presente informe tiene como objetivo realizar un análisis predictivo de la demanda de energía para la empresa EMCALI Empresas Municipales de Cali, a partir de tres variables clave que reflejan, de forma directa e indirecta, el comportamiento del consumo energético en la región.
Consumo de energía de grandes empresas industriales y comerciales del Valle del Cauca (mercado no regulado).
Consumo de energía de pequeñas y grandes empresas en Cali.
Índice de Producción Industrial Regional (IPIR) de Cali.
Variable 1: Consumo de energía del mercado no regulado del Valle Esta variable es particularmente representativa por dos razones:
En primer lugar, el municipio de Yumbo, conocido como la capital industrial de Colombia, colinda con Cali y alberga más de 2.000 empresas. Muchas de estas industrias demandan energía directamente de EMCALI.
En segundo lugar, como capital del departamento del Valle del Cauca, Cali tiende a beneficiarse del dinamismo económico regional; es decir, cuando el Valle crece, Cali también lo hace, y esto se traduce en un mayor consumo energético.
Variable 2: Consumo de energía empresarial en Cali Esta variable refleja de manera directa la demanda de energía local, tanto de pequeñas como de grandes empresas, y por lo tanto constituye un indicador clave del comportamiento de carga para EMCALI.
Variable 3: Índice de Producción Industrial Regional (IPIR) – Cali El IPIR es un indicador relevante para el análisis predictivo, ya que la demanda energética está estrechamente ligada a la actividad industrial. Un aumento en este índice suele estar correlacionado con un mayor consumo energético, dado que la industria representa uno de los principales sectores demandantes de electricidad.
Este conjunto de variables permitirá desarrollar un modelo de análisis robusto que anticipe posibles escenarios de demanda, facilitando una gestión eficiente del suministro energético y una mejor planificación estratégica para el sector en la región.
Instalar/Cargar librerias necesarias para el análisis
#Cargar librerías necesarias
library(tidyr)
library (zoo)
library(readxl) # Para leer archivos Excel
library(tseries) # Para pruebas de estacionariedad
library(forecast) # Para modelado ARIMA y pronósticos
library(ggplot2) # Para visualización de datos
library(plotly) # Para gráficos interactivos
library(timetk) #timetk simplifica y acelera el análisis exploratorio, visualización, y preparación de datos temporales para modelado. Es ideal para quienes trabajan con series temporales en un flujo de trabajo "tidy" y buscan integrar análisis visuales, detección de patrones y forecasting en un solo paquete.
Cargar base de datos
library(readxl)
data_col <- read_excel("D:/Analitica de Datos/Modulo II/Caso No.2/Base Caso2.xlsx",
col_types = c("date", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric", "numeric",
"numeric", "numeric"))
View(data_col)
La metodología empleada en este informe se basa en un análisis univariante de cada una de las variables previamente definidas. El objetivo es aplicar la extraccion de señales para identificar tendencias, patrones estacionales y posibles anomalías que permitan comprender el comportamiento histórico de la demanda energética.
Para ello, se utiliza una base de datos con observaciones mensuales comprendidas entre enero de 2012 y diciembre de 2024, lo que proporciona un horizonte temporal amplio para detectar dinámicas relevantes.
Este enfoque permite no solo visualizar la evolución histórica de cada variable, sino también los cambios en el consumo, aportando una base sólida para la formulación de pronósticos y la toma de decisiones estratégicas en el sector energético.
Declarar las variables como series temporales:
Para un correcto análisis de los datos es indispensable organizar estos de manera cronológica como series de tiempo, para poder identificar tendencias y patrones al momento de hacer la grafica.
Variable 1:Consumo de energía de las grandes empresas industriales y comerciales (mercado no regulado) del Valle.
# Convertir/declarar variable 1 = ENER_V en serie de tiempo mensual
variable1_ts <- ts(data_col$ENER_V, start = c(2012, 1), frequency = 12)
variable1_ts
## Jan Feb Mar Apr May Jun Jul Aug
## 2012 200.3000 201.4000 221.0000 202.6000 220.9000 216.6000 218.9000 220.2000
## 2013 215.7000 212.0000 222.0000 234.7000 232.9000 226.9000 240.9000 234.4000
## 2014 230.4000 218.1000 237.1000 231.6000 238.7000 230.1000 240.6000 236.0000
## 2015 231.6000 222.1000 239.8000 227.4000 235.3000 227.0000 234.2000 247.6000
## 2016 226.2000 230.9000 232.5000 221.7000 230.1000 228.4000 226.9000 251.8000
## 2017 NA 209.2000 225.0000 212.0000 224.2000 216.6000 225.4000 233.8000
## 2018 218.8122 210.6464 226.5548 226.9320 230.2506 229.7543 235.1670 244.0758
## 2019 234.2062 222.0236 238.9558 228.9990 240.8730 226.9174 241.4068 248.9457
## 2020 228.6400 235.2200 227.9800 175.9330 205.8074 206.6000 227.0700 232.4400
## 2021 220.6776 218.5120 236.3354 219.3673 149.2307 219.2868 243.5641 243.6963
## 2022 228.4000 235.3400 255.1300 243.6700 259.4200 238.6800 245.6400 250.2400
## 2023 231.4000 226.4600 245.8800 220.2000 247.2400 230.2800 230.2200 245.1500
## 2024 232.6200 231.5800 235.3600 232.6900 238.0800 221.7400 232.4700 238.8900
## Sep Oct Nov Dec
## 2012 220.7000 225.6000 221.0000 203.6000
## 2013 228.4000 236.9000 228.9000 221.1000
## 2014 235.8000 242.2000 229.7000 224.7000
## 2015 NA 241.9000 229.0000 229.1000
## 2016 234.6000 234.2000 219.9000 NA
## 2017 225.3000 227.7000 224.6000 217.3000
## 2018 234.0968 240.0277 236.8720 224.4440
## 2019 239.5982 243.4795 231.7664 221.6600
## 2020 227.7500 236.0385 233.7300 227.7268
## 2021 238.3515 244.8984 241.8200 234.0800
## 2022 246.2600 247.0900 241.3500 231.1200
## 2023 236.6700 235.1000 227.3800 218.0700
## 2024 235.7500 238.6800 232.3900 228.5900
# Interpolar los valores faltantes (linealmente)
variable1_ts_interp <- na.approx(variable1_ts)
# Calcular estadísticas descriptivas sobre la serie interpolada
descriptive_stats <- data.frame(
Min = min(variable1_ts_interp),
Max = max(variable1_ts_interp),
Media = mean(variable1_ts_interp),
Mediana = median(variable1_ts_interp),
DesviacionEstandar = sd(variable1_ts_interp),
CoefVar = sd(variable1_ts_interp) / mean(variable1_ts_interp)
)
print(descriptive_stats)
## Min Max Media Mediana DesviacionEstandar CoefVar
## 1 149.2307 259.42 229.3987 230.2653 13.29511 0.05795635
# Interpolar los valores faltantes
variable1_ts_interp <- na.approx(variable1_ts)
# Convertir la serie interpolada a data frame con fechas reales
df_variable1 <- data.frame(
fecha = as.Date(as.yearmon(time(variable1_ts_interp))),
valor = as.numeric(variable1_ts_interp)
)
# Crear gráfico ggplot
grafico_interactivo <- ggplot(df_variable1, aes(x = fecha, y = valor)) +
geom_line(color = "steelblue", size = 1) +
labs(
title = "Gráfico 1. Consumo de energía de las grandes empresas industriales y comerciales del Valle",
x = "Fecha",
y = "GWh"
) +
theme_minimal()
# Convertir a gráfico interactivo
ggplotly(grafico_interactivo)
A partir de las estadísticas descriptivas básicas de la variable #1, se observa que el consumo mínimo de energía por parte de las empresas industriales y comerciales del Valle del Cauca se registró en mayo de 2021, alcanzando un valor de 149,2307 GWh. Este comportamiento coincide con el periodo del paro nacional, durante el cual se presentaron bloqueos generalizados en la región, afectando significativamente la actividad productiva. Es importante resaltar que dicho valor es inferior al registrado durante el confinamiento por la pandemia de COVID-19, cuando el consumo cayó a 175,9330 GWh, lo que evidencia el fuerte impacto del paro sobre la demanda energética del sector. En contraste, el consumo promedio de energía en la última década se ha situado en 229,3987 GWh, con una desviación estándar de 13,2951 GWh, lo cual indica una variabilidad moderada en la serie. Estos datos permiten identificar de manera precisa los eventos atípicos y su efecto en la dinámica energética regional. Por otra parte, el análisis sugiere que la demanda de energía en el Valle del Cauca ha logrado recuperar los niveles registrados antes de la pandemia de COVID-19.
Variable 2: Consumo de energia (pequeñas y grandes empresas) en Cali.
# Convertir/declarar variable 2 = ENER_CALI en serie de tiempo mensual
variable2_ts <- ts(data_col$ENER_CALI, start = c(2012, 1), frequency = 12)
variable2_ts
## Jan Feb Mar Apr May Jun Jul Aug
## 2012 69379734 68346783 69585382 67028317 68422194 68707263 70966132 70606450
## 2013 72484891 68481359 70141972 71172853 71211683 69911128 72675502 71883977
## 2014 71045111 68078756 72980168 72009619 74263593 71046360 75207559 74079893
## 2015 76126651 73419334 78550716 79206134 76270353 78528134 79902889 84518504
## 2016 80072832 78668248 83858120 77884938 76408062 75925321 76274460 78184606
## 2017 74520537 70126757 75457634 72283841 72546718 74486294 75093711 77097963
## 2018 74137644 70797415 77116684 74683687 73731901 73132318 74963451 77137430
## 2019 77175702 73065423 79561766 75295272 75228315 75273077 78775292 79994268
## 2020 79539284 76765155 77465284 60759080 49201417 50958801 56568018 59083833
## 2021 68164952 63733083 68340778 63644601 60927547 59668697 65844999 66791128
## 2022 63528491 61491534 72204398 68425277 72445423 63851596 66627372 68637208
## 2023 64970450 63226074 69693459 63767272 71927402 67781963 69331444 71565510
## 2024 69272014 70036080 70878351 70090436 70417168 65586094 68766311 71220231
## Sep Oct Nov Dec
## 2012 71077070 71866697 69789982 69809336
## 2013 72581354 73353073 71495088 70050821
## 2014 74705434 75893275 72954572 74211194
## 2015 81148853 83913224 80781121 80100534
## 2016 79558722 76809456 74046181 74521602
## 2017 78870899 78096493 74920091 75498647
## 2018 76662316 78907443 74260793 76270009
## 2019 81381756 81637548 77180278 78830924
## 2020 61378156 66465618 68121584 67841806
## 2021 66323087 66969830 64851725 65926675
## 2022 66943485 67396543 65894026 66293383
## 2023 70401242 70121508 67896341 65881643
## 2024 70913629 71021102 66290757 67835511
# Calcular estadísticas descriptivas básicas
descriptive_stats <- data.frame(
Min = min(variable2_ts),
Max = max(variable2_ts),
Media = mean(variable2_ts),
Mediana = median(variable2_ts),
DesviacionEstandar = sd(variable2_ts),
CoefVar = sd(variable2_ts) / mean(variable2_ts)
)
print(descriptive_stats)
## Min Max Media Mediana DesviacionEstandar CoefVar
## 1 49201417 84518504 71758652 71875337 5946893 0.08287353
# Convertir la serie de tiempo a un data frame con fechas reales
df_variable2 <- data.frame(
fecha = as.Date(as.yearmon(time(variable2_ts))), # convierte índice ts en fechas
valor = as.numeric(variable2_ts) # extrae los valores numéricos
)
# Crear el gráfico de línea con ggplot
grafico_energia <- ggplot(df_variable2, aes(x = fecha, y = valor)) +
geom_line(color = "darkgreen", size = 1) +
labs(
title = "Gráfico 2. Evolución del consumo de energía en Cali (ENER_CALI)",
x = "Fecha",
y = "GWh"
) +
theme_minimal()
# Convertir a gráfico interactivo
ggplotly(grafico_energia)
La estadística descriptiva básica de la variable #2 muestra que el consumo de energía del sector industrial y comercial en Cali seguía una tendencia creciente antes de 2020, reflejando una expansión progresiva del tejido empresarial de la ciudad. No obstante, el impacto económico derivado de la pandemia de COVID-19 fue significativo, llevando el consumo energético a un mínimo histórico de 49,201 GWh. El análisis de la serie de tiempo revela que, a pesar de una leve recuperación posterior, la demanda de energía en Cali aún no alcanza los niveles registrados en 2012. Este comportamiento sugiere que EMCALI cuenta actualmente con una infraestructura energética sobredimensionada respecto a la demanda real.
Variable 3: Índice de Producción Industrial (IPIR) Cali.
# Convertir/declarar variable 3 = IPIR_CALI en serie de tiempo mensual
variable3_ts <- ts(data_col$IPIR_CALI, start = c(2012, 1), frequency = 12)
variable3_ts
## Jan Feb Mar Apr May Jun Jul
## 2012 96.47151 101.89722 107.43327 98.47965 104.51982 106.11454 105.94103
## 2013 93.69983 93.53270 95.12147 106.11457 104.44380 107.49263 111.44949
## 2014 98.13421 101.15981 105.46999 104.37586 104.60483 104.35731 109.90205
## 2015 102.11504 107.40357 111.24739 107.41472 107.90188 110.71140 112.16074
## 2016 104.96732 109.38748 108.97920 107.20438 104.07097 108.11365 103.99047
## 2017 100.22203 102.06038 106.84059 100.92828 103.58373 108.64599 107.97362
## 2018 100.52465 103.07804 107.52431 106.97189 108.88635 108.82576 110.75496
## 2019 104.31989 108.36834 112.78477 110.74097 118.10134 113.66469 114.34179
## 2020 104.42163 110.08244 107.53392 92.19771 98.84423 106.35106 109.87100
## 2021 100.93980 104.76326 107.43094 97.33371 52.56788 101.04241 124.88593
## 2022 105.20084 104.88014 118.25102 113.47250 116.38268 115.92182 121.74192
## 2023 106.59331 108.27840 116.65529 110.15517 117.11739 118.34544 116.78418
## 2024 109.96371 115.47878 114.37051 121.84172 122.02643 119.89085 119.44905
## Aug Sep Oct Nov Dec
## 2012 107.06245 109.51453 116.58799 112.16612 106.41190
## 2013 110.48614 111.73036 116.18060 108.94420 106.24920
## 2014 108.63293 111.80402 116.35420 109.33215 111.67265
## 2015 111.45782 114.56244 118.01970 114.27364 114.38366
## 2016 114.75106 114.25847 115.65555 113.09275 112.05771
## 2017 112.68312 113.10225 116.27296 113.84054 113.11650
## 2018 115.53036 114.93168 119.94612 116.72999 109.58689
## 2019 113.83002 113.34219 117.95999 113.45428 113.20773
## 2020 108.68535 112.61665 116.42163 113.40291 109.39146
## 2021 127.58523 127.32584 124.93936 119.20490 118.04875
## 2022 125.74966 127.96142 129.59093 128.40464 121.89443
## 2023 121.57073 124.15010 124.79659 121.83217 119.30224
## 2024 119.67162 116.32233 118.35843 114.83672 111.36085
# Calcular estadísticas descriptivas básicas
descriptive_stats <- data.frame(
Min = min(variable3_ts),
Max = max(variable3_ts),
Media = mean(variable3_ts),
Mediana = median(variable3_ts),
DesviacionEstandar = sd(variable3_ts),
CoefVar = sd(variable3_ts) / mean(variable3_ts)
)
print(descriptive_stats)
## Min Max Media Mediana DesviacionEstandar CoefVar
## 1 52.56788 129.5909 110.7897 110.748 8.802881 0.07945576
# Convertir la serie de tiempo a un data frame con fechas reales
df_variable3 <- data.frame(
fecha = as.Date(as.yearmon(time(variable3_ts))), # convierte índice ts en fechas
valor = as.numeric(variable3_ts) # extrae los valores numéricos
)
# Crear el gráfico de línea
grafico_variable3 <- ggplot(df_variable3, aes(x = fecha, y = valor)) +
geom_line(color = "black", size = 1) +
labs(
title = "Gráfico 3. Evolución Índice de Producción Industrial (IPIR) Cali",
x = "Fecha",
y = "Índice"
) +
theme_minimal()
# Convertir a gráfico interactivo
ggplotly(grafico_variable3)
El Índice de Producción Industrial (IPIR) de Cali, a diferencia de las otras dos variables analizadas, muestra un patrón estacional en su comportamiento: caídas recurrentes en el primer y cuarto trimestre de cada año, seguidas por una recuperación durante el segundo y tercer trimestre. Este comportamiento contrasta con la serie de consumo de energía en Cali, la cual no presenta una estacionalidad tan marcada.
El descenso más pronunciado del IPIR se registró en mayo de 2021, coincidiendo con el paro nacional, alcanzando un valor mínimo de 52,567 puntos. Por otra parte, el análisis sugiere que la producción industrial en Cali ha logrado recuperar sus niveles prepandémicos, acercándose actualmente a su promedio de los últimos 10 años de 110,7897.
Esto indicaría que el bajo nivel de consumo de energía en Cali no se debe al sector industrial.
La extracción de señales es una herramienta clave para comprender el comportamiento dinámico de las series de tiempo. Este enfoque permite aislar componentes como la tendencia, la estacionalidad y residuo, lo que facilita la identificación de patrones ocultos que podrían pasar desapercibidos en un análisis superficial. Su aplicación proporciona una base más sólida para la toma de decisiones estratégicas.
Variable 1 = Consumo de energía de las grandes empresas industriales y comerciales (mercado no regulado) del Valle.
#Cargar Biblioteca requerida para rellenar datos faltantes
library(zoo)
# Interpola los valores NA
variable1_interp <- na.approx(variable1_ts)
# Asegúrate de que siga siendo objeto de clase ts
variable1_ts_clean <- ts(variable1_interp, start = start(variable1_ts), frequency = frequency(variable1_ts))
# Aplica STL
stl_decomp_var1 <- stl(variable1_ts_clean, s.window = "periodic")
# Convertir la descomposición a un data frame para graficar con ggplot2
stl_df_var1 <- data.frame(
Time = rep(time(variable1_ts), 4), # Tiempo repetido para cada componente
Value = c(stl_decomp_var1$time.series[, "seasonal"],
stl_decomp_var1$time.series[, "trend"],
stl_decomp_var1$time.series[, "remainder"],
variable1_ts),
Component = rep(c("Estacional", "Tendencia", "Residuo", "Serie Original"), each = length(variable1_ts))
)
# Crear gráfico con ggplot2
p <- ggplot(stl_df_var1, aes(x = Time, y = Value, color = Component)) +
geom_line() +
facet_wrap(~Component, scales = "free_y", ncol = 1) +
theme_minimal() +
labs(title = "Grafico 4.Descomposición temporal Var. Consumo de energía grandes empresas industriales y comerciales del Valle",
x = "Anual",
y = "GwH")
# Convertir a gráfico interactivo con plotly
ggplotly(p)
El gráfico 4. evidencia que la serie de tiempo del consumo energético presenta un componente estacional, con picos recurrentes en julio y niveles bajos de consumo entre noviembre y enero de cada año. Esta dinámica sugiere una relación directa con los periodos vacacionales de fin de año, durante los cuales se reduce la actividad industrial y comercial. Durante los años correspondientes a la pandemia por COVID-19 y el paro nacional, se observan valores atípicos que alteran el patrón habitual de la serie. Estos puntos anómalos introducen ruido temporal. Por su parte, el componente de tendencia permite una lectura más estructural del comportamiento de la serie. Este muestra que, a pesar de las perturbaciones, el consumo de energía ha seguido una trayectoria general de crecimiento, con fluctuaciones notables entre 2019 y 2022.
Variable 2 = Consumo de energia (pequeñas y grandes empresas) en Cali.
# Descomposición de la serie temporal
stl_decomp_var2 <- stl(variable2_ts, s.window = "periodic")
# Convertir la descomposición a un data frame para graficar con ggplot2
stl_df_var2 <- data.frame(
Time = rep(time(variable2_ts), 4), # Tiempo repetido para cada componente (son 4 componentes)
Value = c(stl_decomp_var2$time.series[, "seasonal"],
stl_decomp_var2$time.series[, "trend"],
stl_decomp_var2$time.series[, "remainder"],
variable1_ts),
Component = rep(c("Estacional", "Tendencia", "Residuo", "Serie Original"), each = length(variable2_ts))
)
# Crear gráfico con ggplot2
p <- ggplot(stl_df_var2, aes(x = Time, y = Value, color = Component)) +
geom_line() +
facet_wrap(~Component, scales = "free_y", ncol = 1) +
theme_minimal() +
labs(title = "Grafico 5. Descomposición temporal Var. Consumo de energia empresas en Cali",
x = "Año",
y = "GwH")
# Convertir a gráfico interactivo con plotly
ggplotly(p)
El gráfico 5 muestra que la serie de tiempo correspondiente al consumo energético en Cali evidencia un componente estacional, con un patrón de aumento sostenido entre los meses de mayo y septiembre de cada año. Este comportamiento sugiere una posible relación con el ciclo productivo local, donde la actividad económica tiende a incrementarse en el segundo y tercer trimestre del año. Al igual que en la serie correspondiente al consumo de energía en el Valle del Cauca, se genera ruido significativo por los mismos eventos. El componente de tendencia confirma lo observado previamente en la gráfica de la serie original, y se identifica una caída abrupta en septiembre de 2019 de la cual el consumo energético no ha logrado recuperar los niveles registrados previamente. Esta tendencia descendente sugiere que, a diferencia del comportamiento observado a nivel regional, la ciudad de Cali aún no ha restablecido plenamente su demanda de energía.
Variable 3 = Índice de Producción Industrial (IPIR) Cali.
# Descomposición de la serie temporal
stl_decomp_var3 <- stl(variable3_ts, s.window = "periodic")
# Convertir la descomposición a un data frame para graficar con ggplot2
stl_df_var3 <- data.frame(
Time = rep(time(variable3_ts), 4), # Tiempo repetido para cada componente
Value = c(stl_decomp_var3$time.series[, "seasonal"],
stl_decomp_var3$time.series[, "trend"],
stl_decomp_var3$time.series[, "remainder"],
variable3_ts),
Component = rep(c("Estacional", "Tendencia", "Residuo", "Serie Original"), each = length(variable3_ts))
)
# Crear gráfico con ggplot2
p <- ggplot(stl_df_var3, aes(x = Time, y = Value, color = Component)) +
geom_line() +
facet_wrap(~Component, scales = "free_y", ncol = 1) +
theme_minimal() +
labs(title = "Grafico 6. Descomposición temporal Var. Índice de Producción Industrial (IPIR) Cali",
x = "Anual",
y = "Indice")
# Convertir a gráfico interactivo con plotly
ggplotly(p)
La descomposición temporal de la serie del IPIR para Cali revela un componente estacional claramente definido, con un patrón cíclico que se repite entre los meses de abril y enero de cada año. Durante el periodo comprendido entre abril y septiembre, se observa un* incremento sostenido en la producción industrial, alcanzando sus máximos anuales, seguido de una caída pronunciada hacia enero, posiblemente asociada a la reducción de la actividad económica durante la temporada de fin de año*, cuando la ciudad entra en un periodo festivo marcado por la tradicional Feria de Cali.
En cuanto al componente de tendencia, destaca un aspecto clave: hacia diciembre de 2024, el índice muestra una clara tendencia descendente, registrando valores similares a los observados en agosto de 2021, inmediatamente después del paro nacional. Este evento tuvo un impacto profundo sobre la estructura productiva de la ciudad y, según se desprende de la tendencia actual, la industria caleña podría estar enfrentando nuevamente una contracción significativa.
Para reducir el ruido generado por la estacionalidad observada en las tres variables, se procede a realizar un ajuste estacional. Esta técnica permite aislar el componente estacional de las series de tiempo, facilitando una lectura más clara de las tendencias subyacentes y mejorando la precisión en el análisis comparativo y la toma de decisiones.
ESTACIONALIDAD: Variable #1 (Consumo de energía de las grandes empresas industriales y comerciales (mercado no regulado) del Valle) ajustada por estacionalidad
# Extraer los componentes de la descomposición
variable1_sa <- variable1_ts - stl_decomp_var1$time.series[, "seasonal"]
ESTACIONALIDAD: Variable #2 (Consumo de energia (pequeñas y grandes empresas) en Cali) ajustada por estacionalidad
# Extraer los componentes de la descomposición
variable2_sa <- variable2_ts - stl_decomp_var2$time.series[, "seasonal"]
ESTACIONALIDAD: Varibale #3 (Índice de Producción Industrial (IPIR) Cali) ajustada por estacionalidad
# Extraer los componentes de la descomposición
variable3_sa <- variable3_ts - stl_decomp_var3$time.series[, "seasonal"]
Cruzar la grafica de la serie ajustada por estacionalidad con la grafica de la serie orginal Al realizar este cruce de gráficas, es posible identificar si el componente estacional ejerce una influencia significativa sobre la variable en estudio. Este análisis permite determinar si estos afectan de manera sistemática el comportamiento de la serie.
Gráfico serie original VS ajustada: Variable #1 (Consumo de energía de las grandes empresas industriales y comerciales (mercado no regulado) del Valle) ajustada por estacionalidad
# Crear vector de fechas correctamente alineado con la serie
fechas_var1 <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variable1_ts))
# Gráfico mejorado con fechas en el eje X
grafico_ajustada_var1 <- ggplot() +
geom_line(aes(x = fechas_var1, y = variable1_ts), color = "grey", size = 0.5, linetype = "solid", name = "Serie Original") +
geom_line(aes(x = fechas_var1, y = variable1_sa), color = "black", size = 0.6, linetype = "solid", name = "Serie Ajustada") +
ggtitle("Grafico 7. (Varible 1) Serie Original vs Serie Ajustada por Estacionalidad") +
xlab("Tiempo") +
ylab("Unidad de medida variable 1") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotar etiquetas para mejor visualización
# Convertir a gráfico interactivo
ggplotly(grafico_ajustada_var1)
Gráfico serie original VS ajustada: Variable #2 (Consumo de energia (pequeñas y grandes empresas) en Cali) ajustada por estacionalidad
# Crear vector de fechas correctamente alineado con la serie
fechas_var2 <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variable2_ts))
# Gráfico mejorado con fechas en el eje X
grafico_ajustada_var2 <- ggplot() +
geom_line(aes(x = fechas_var2, y = variable2_ts), color = "grey", size = 0.5, linetype = "solid", name = "Serie Original") +
geom_line(aes(x = fechas_var2, y = variable2_sa), color = "black", size = 0.6, linetype = "solid", name = "Serie Ajustada") +
ggtitle("Grafico 8. (Varible 2)Serie Original vs Serie Ajustada por Estacionalidad") +
xlab("Tiempo") +
ylab("Unidad de medida variable 2") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotar etiquetas para mejor visualización
# Convertir a gráfico interactivo
ggplotly(grafico_ajustada_var2)
Gráfico serie original VS ajustada: Varibale #3 (Índice de Producción Industrial (IPIR) Cali) ajustada por estacionalidad
# Crear vector de fechas correctamente alineado con la serie
fechas_var3 <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variable3_ts))
# Gráfico mejorado con fechas en el eje X
grafico_ajustada_var3 <- ggplot() +
geom_line(aes(x = fechas_var3, y = variable3_ts), color = "grey", size = 0.5, linetype = "solid", name = "Serie Original") +
geom_line(aes(x = fechas_var3, y = variable3_sa), color = "black", size = 0.6, linetype = "solid", name = "Serie Ajustada") +
ggtitle("Grafico 9. (Varible 3)Serie Original vs Serie Ajustada por Estacionalidad") +
xlab("Tiempo") +
ylab("Unidad de medida variable 3") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotar etiquetas para mejor visualización
# Convertir a gráfico interactivo
ggplotly(grafico_ajustada_var3)
Interpretacion serie original VS ajustada (ESTACIONALIDAD)
En general, la influencia de la estacionalidad en las tres variables analizadas es relativamente baja. Esto se evidencia al comparar la serie original con la serie ajustada por estacionalidad, ya que ambas presentan trayectorias muy similares. La alta coincidencia entre ambas líneas indica que los patrones estacionales no ejercen un efecto significativo sobre la dinámica general de las variables. Por tanto, se puede inferir que las fluctuaciones observadas responden principalmente a tendencias estructurales o a eventos extraordinarios, más que a comportamientos cíclicos recurrentes.
Para enfocar el análisis en los cambios estructurales de la serie y facilitar la proyección de escenarios futuros, así como la anticipación de posibles crisis u oportunidades, es necesario ajustar la variable por el componente de tendencia. Este ajuste permite aislar el comportamiento de fondo de la serie, eliminando las fluctuaciones temporales y revelando la dirección general del fenómeno a lo largo del tiempo.
Gráfico serie original VS ajustada: Variable #1 (Consumo de energía de las grandes empresas industriales y comerciales (mercado no regulado) del Valle) ajustada por tendencia
library(ggplot2)
library(plotly)
# Convertir la serie a un vector numérico
variable1_vec <- as.numeric(variable1_ts)
tendencia_var1 <- as.numeric(stl_decomp_var1$time.series[, "trend"])
# Asegurar que 'fechas' tenga la misma longitud
fechas <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variable1_ts))
# Gráfico interactivo de la serie original vs tendencia
grafico_tendencia_var1 <- ggplot() +
geom_line(aes(x = fechas, y = variable1_vec, color = "Serie Original"), size = 0.7, linetype = "solid") +
geom_line(aes(x = fechas, y = tendencia_var1, color = "Tendencia"), size = 0.8, linetype = "solid") +
scale_color_manual(values = c("Serie Original" = "grey", "Tendencia" = "black")) +
ggtitle("Grafico 10. (Varible 1) Serie Original vs Tendencia") +
xlab("Tiempo") +
ylab("Unidad de medida Variable 1") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotar etiquetas del eje X
# Convertir a gráfico interactivo con plotly
ggplotly(grafico_tendencia_var1)
El Gráfico 10 permite observar que el consumo de energía en el Valle del Cauca muestra señales de estar entrando en una etapa de estabilización, en torno a los 233,246 GWh. Este valor es muy similar a los niveles registrados antes de la pandemia.
Gráfico serie original VS ajustada: Variable #2 (Consumo de energia (pequeñas y grandes empresas) en Cali) ajustada por tendencia
library(ggplot2)
library(plotly)
# Convertir la serie a un vector numérico
variable2_vec <- as.numeric(variable2_ts)
tendencia_var2 <- as.numeric(stl_decomp_var2$time.series[, "trend"])
# Asegurar que 'fechas' tenga la misma longitud
fechas <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variable2_ts))
# Gráfico interactivo de la serie original vs tendencia
grafico_tendencia_var2 <- ggplot() +
geom_line(aes(x = fechas, y = variable2_vec, color = "Serie Original"), size = 0.7, linetype = "solid") +
geom_line(aes(x = fechas, y = tendencia_var2, color = "Tendencia"), size = 0.8, linetype = "solid") +
scale_color_manual(values = c("Serie Original" = "grey", "Tendencia" = "black")) +
ggtitle("Grafico 11. (Varible 2) Serie Original vs Tendencia") +
xlab("Tiempo") +
ylab("Unidad de medida Variable 2") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotar etiquetas del eje X
# Convertir a gráfico interactivo con plotly
ggplotly(grafico_tendencia_var2)
El Gráfico 11 indica que la demanda de energía por parte de pequeñas y grandes empresas en Cali aún no ha logrado recuperarse. Por el contrario, la tendencia sugiere que podría estar entrando en una nueva etapa de contracción.
Gráfico serie original VS ajustada: Varibale #3 (Índice de Producción Industrial (IPIR) Cali) ajustada por tendencia
library(ggplot2)
library(plotly)
# Convertir la serie a un vector numérico
variable3_vec <- as.numeric(variable3_ts)
tendencia_var3 <- as.numeric(stl_decomp_var3$time.series[, "trend"])
# Asegurar que 'fechas' tenga la misma longitud
fechas <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variable3_ts))
# Gráfico interactivo de la serie original vs tendencia
grafico_tendencia_var3 <- ggplot() +
geom_line(aes(x = fechas, y = variable3_vec, color = "Serie Original"), size = 0.7, linetype = "solid") +
geom_line(aes(x = fechas, y = tendencia_var3, color = "Tendencia"), size = 0.8, linetype = "solid") +
scale_color_manual(values = c("Serie Original" = "grey", "Tendencia" = "black")) +
ggtitle("Grafico 12. (Varible 3) Serie Original vs Tendencia") +
xlab("Tiempo") +
ylab("Unidad de medida Variable 3") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotar etiquetas del eje X
# Convertir a gráfico interactivo con plotly
ggplotly(grafico_tendencia_var3)
El Gráfico 12 refuerza lo observado en el gráfico anterior, al evidenciar que la producción industrial de Cali atraviesa una fase de contracción. Su comportamiento reciente guarda similitud con el registrado en septiembre de 2019, lo que sugiere que el efecto de recuperación postpandemia podría haber llegado a su fin y que la industria estaría retornando a un escenario de desaceleración.
Tasa de crecimiento de la serie original para hacer comparativo con la grafica tendencia:
Variable 1: Calculo de tasa de crecimiento y validacion de longitud
#Cálculo de la tasa de crecimiento anual correctamente alineada
tasa_crecimiento_var1 <- (variable1_ts[(13:length(variable1_ts))] / variable1_ts[1:(length(variable1_ts) - 12)] - 1) * 100
tasa_tendencia_var1 <- (tendencia_var1[(13:length(tendencia_var1))] / tendencia_var1[1:(length(tendencia_var1) - 12)] - 1) * 100
# Crear vector de fechas corregido, es decir que inicie desde enero 2013
fechas_corregidas_var1 <- seq(from = as.Date("2013-01-01"), by = "month", length.out = length(tasa_crecimiento_var1))
# Verificar longitudes
print(length(fechas_corregidas_var1))
## [1] 144
print(length(tasa_crecimiento_var1))
## [1] 144
print(length(tasa_tendencia_var1))
## [1] 144
Gráfico Variable 1:Tasa de crecimiento anual
library(ggplot2)
library(plotly)
# Gráfico de la tasa de crecimiento anual variable 1
grafico_crecimiento_var1 <- ggplot() +
geom_line(aes(x = fechas_corregidas_var1, y = tasa_crecimiento_var1), color = "grey", size = 0.7) +
geom_line(aes(x = fechas_corregidas_var1, y = tasa_tendencia_var1), color = "black", size = 0.8, linetype = "dashed") +
ggtitle("Grafico 13. (Varible 1) Tasa de crecimiento anual % de la serie Original y la tendencia") +
xlab("Tiempo") +
ylab("% de Crecimiento Anual") +
theme_minimal()
# Convertir a gráfico interactivo
ggplotly(grafico_crecimiento_var1)
La gráfica evidencia que la variable experimentó cambios estructurales como resultado de la pandemia y el efecto rebote que esta generó sobre la economía del Valle, lo cual provocó una distorsión significativa en el consumo de energía. No obstante, se puede inferir que el comportamiento de la variable muestra señales de estabilización en los periodos más recientes.
Variable 2: Calculo de tasa de crecimiento y validacion de longitud
#Cálculo de la tasa de crecimiento anual correctamente alineada
tasa_crecimiento_var2 <- (variable2_ts[(13:length(variable2_ts))] / variable2_ts[1:(length(variable2_ts) - 12)] - 1) * 100
tasa_tendencia_var2 <- (tendencia_var2[(13:length(tendencia_var2))] / tendencia_var2[1:(length(tendencia_var2) - 12)] - 1) * 100
# Crear vector de fechas corregido
fechas_corregidas_var2 <- seq(from = as.Date("2013-01-01"), by = "month", length.out = length(tasa_crecimiento_var2))
# Verificar longitudes
print(length(fechas_corregidas_var2))
## [1] 144
print(length(tasa_crecimiento_var2))
## [1] 144
print(length(tasa_tendencia_var2))
## [1] 144
Gráfico Variable 2:Tasa de crecimiento anual
# Gráfico de la tasa de crecimiento anual variable 2
grafico_crecimiento_var2 <- ggplot() +
geom_line(aes(x = fechas_corregidas_var2, y = tasa_crecimiento_var2), color = "grey", size = 0.7) +
geom_line(aes(x = fechas_corregidas_var2, y = tasa_tendencia_var2), color = "black", size = 0.8, linetype = "dashed") +
ggtitle("Grafico 14. (Varible 2) Tasa de crecimiento anual % de la serie Original y la Tendencia") +
xlab("Tiempo") +
ylab("% de Crecimiento Anual") +
theme_minimal()
# Convertir a gráfico interactivo
ggplotly(grafico_crecimiento_var2)
El Gráfico 14 no logra suavizar completamente el comportamiento de la serie, ya que continúa mostrando una alta volatilidad con picos y caídas a lo largo de los últimos 10 años. En particular, se destaca un pico al alza en agosto de 2015 y una caída pronunciada en septiembre de 2020, atribuible al impacto de la pandemia. Esto sugiere que la variable ha experimentadocambios estructurales significativos en la última década, lo cual limita la capacidad del componente de tendencia para capturar un patrón claro y estable en el tiempo.
Variable 2: Calculo de tasa de crecimiento y validacion de longitud
#Cálculo de la tasa de crecimiento anual correctamente alineada
tasa_crecimiento_var3 <- (variable3_ts[(13:length(variable3_ts))] / variable3_ts[1:(length(variable3_ts) - 12)] - 1) * 100
tasa_tendencia_var3 <- (tendencia_var3[(13:length(tendencia_var3))] / tendencia_var3[1:(length(tendencia_var3) - 12)] - 1) * 100
# Crear vector de fechas corregido
fechas_corregidas_var3 <- seq(from = as.Date("2013-01-01"), by = "month", length.out = length(tasa_crecimiento_var3))
# Verificar longitudes
print(length(fechas_corregidas_var3))
## [1] 144
print(length(tasa_crecimiento_var3))
## [1] 144
print(length(tasa_tendencia_var3))
## [1] 144
Gráfico Variable 3:Tasa de crecimiento anual
# Gráfico de la tasa de crecimiento anual variable 3
grafico_crecimiento_var3 <- ggplot() +
geom_line(aes(x = fechas_corregidas_var3, y = tasa_crecimiento_var3), color = "grey", size = 0.7) +
geom_line(aes(x = fechas_corregidas_var3, y = tasa_tendencia_var3), color = "black", size = 0.8, linetype = "dashed") +
ggtitle("Grafico 15. (Varible 3) Tasa de crecimiento anual % de la serie Original y la tendencia") +
xlab("Tiempo") +
ylab("% de Crecimiento Anual") +
theme_minimal()
# Convertir a gráfico interactivo
ggplotly(grafico_crecimiento_var3)
La serie de tiempo suavizada del Índice de Producción Industrial (IPIR) de Cali muestra que esta variable ha sido históricamente estable y de bajo dinamismo, con tasas de crecimiento anual relativamente constantes durante la última década. Los únicos cambios estructurales significativos se presentan durante la pandemia por COVID-19 y el efecto rebote posterior, que generaron distorsiones abruptas tanto a la baja como al alza, reflejando el impacto macroeconómico de estos eventos en la industria local. Asimismo, la tendencia reciente sugiere que la producción industrial en Cali está entrando en una nueva fase de contracción, similar a la trayectoria descendente observada antes de la pandemia. Esta señal plantea alertas sobre una posible desaceleración estructural en el sector industrial, lo cual podría tener implicaciones negativas sobre la recuperación económica sostenida de la ciudad.
Para el desarrollo del pronóstico de corto plazo mediante modelado ARIMA, se seleccionó como variable objetivo el consumo de energía de las grandes empresas industriales y comerciales (mercado no regulado) del Valle del Cauca. Esta decisión se basa en criterios de relevancia económica, operativa y financiera, teniendo en cuenta su impacto directo sobre el desempeño de EMCALI como empresa proveedora del servicio.
Relación directa con los ingresos operacionales: La demanda de energía por parte del mercado no regulado constituye una de las principales fuentes de facturación para EMCALI. Su evolución refleja la dinámica real de la prestación del servicio y, por tanto, su análisis permite anticipar el comportamiento de los flujos de caja a corto y mediano plazo.
Indicador representativo de la actividad económica regional: Este segmento está conformado principalmente por empresas industriales y comerciales de alto consumo, lo cual convierte a esta variable en un indicador confiable del nivel de actividad económica en el sector productivo, así como de la eficiencia y cobertura del servicio energético.
Elemento clave para la planeación estratégica y financiera: Al anticipar variaciones en la demanda energética, EMCALI puede optimizar su planeación de oferta, gestionar eficientemente sus contratos de compra en bolsa y garantizar la sostenibilidad financiera del negocio. Además, este análisis facilita la evaluación de riesgos asociados a cambios en la estructura del mercado o en el comportamiento de sus principales clientes.
División en conjunto de entrenamiento y prueba para la variable 1 que es la elegida para pronosticar
El código siguiente divide una serie temporal (variable1_ts) en dos subconjuntos:
Conjunto de entrenamiento (train): Datos desde enero de 2012 hasta septiembre de 2024. Conjunto de prueba (test): Datos desde octubre de 2024 hasta diciembre de 2024.
Esto se hace para evaluar el desempeño de modelos de predicción en datos no vistos.
# Esta división idealmente podria se 80%-70% de los datos para entrenamiento y 20%-30% para prueba o test
# En este ejemplo el conjunto de entrenamiento es: Enero 2012-Septiembre 2024 y el conjunto de prueba o test: noviembre 2024-diciembre 2024
train_size <- length(variable1_ts) - 3 # Se deja fuera los últimos 3 valores para usarlos como set de prueba.
train_ts <- window(variable1_ts, end = c(2024, 9)) # Entrenamiento hasta septiembre 2024
test_ts <- window(variable1_ts, start = c(2024, 10)) # Prueba inicia desde oct2024
Identificación automática del modelo ARIMA
library(forecast)
# Ajustar un modelo ARIMA automático sin estacionalidad, por eso se pone seasonal=FALSE
auto_arima_model_no_seasonal <- auto.arima(train_ts, seasonal = FALSE)
# Mostrar el modelo seleccionado
summary(auto_arima_model_no_seasonal)
## Series: train_ts
## ARIMA(1,1,1) with drift
##
## Coefficients:
## ar1 ma1 drift
## 0.3129 -0.8970 0.1322
## s.e. 0.1426 0.0994 0.1593
##
## sigma^2 = 147.9: log likelihood = -582.89
## AIC=1173.79 AICc=1174.06 BIC=1185.88
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 0.3849432 11.99776 8.254645 -0.1145889 3.75019 0.7825953
## ACF1
## Training set -0.03586551
Estimación del modelo identificado automatico y validación de Significancia de coeficientes
library(lmtest)
# Evaluar la significancia estadística de los coeficientes del modelo ARIMA
coeftest(auto_arima_model_no_seasonal)
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 0.312901 0.142645 2.1936 0.02827 *
## ma1 -0.896977 0.099416 -9.0225 < 2e-16 ***
## drift 0.132186 0.159273 0.8299 0.40658
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Ajuste del modelo ARIMA(4,1,2) automático sin parte estacional y crearlo como variable darima_auto para luego poder graficarlo y crear la tabla
darima_auto <- Arima(train_ts,
order = c(4, 1, 2)) # Especificamos directamente (p=4, d=1, q=2)
# Mostrar resumen del modelo ajustado
summary(darima_auto)
## Series: train_ts
## ARIMA(4,1,2)
##
## Coefficients:
## ar1 ar2 ar3 ar4 ma1 ma2
## -0.3508 0.3740 0.1349 0.0092 -0.2638 -0.6836
## s.e. 0.4936 0.1976 0.1112 0.0930 0.4860 0.4727
##
## sigma^2 = 149.2: log likelihood = -582.31
## AIC=1178.62 AICc=1179.4 BIC=1199.79
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 1.881603 11.92678 8.059998 0.5360136 3.64608 0.7641415 -0.03157635
Validación de residuales o errores del modelo
# Diagnóstico del modelo (los residuos deben ser ruido blanco)
checkresiduals(darima_auto) # Verificar si los residuos son aleatorios y no presentan patrones
##
## Ljung-Box test
##
## data: Residuals from ARIMA(4,1,2)
## Q* = 34.459, df = 18, p-value = 0.01105
##
## Model df: 6. Total lags used: 24
Evaluación de los residuos del modelo ARIMA
En la gráfica de la serie temporal de los residuos se observa que estos parecen relativamente centrados alrededor de 0 a excepción del año 2019- 2020 registrando valores atipicos de -25 y-75 por situación de pandemia.
La gráfica ACF de los residuos, muestra que la mayoría de los puntos están dentro de las bandas azules, mostrando ausencia de autocorrelación significativa.
El histograma de los residuos, es aproximadamente simétrica y centrada en cero, lo que indica una distribución cercana a la normal.
Pronóstico modelo ARIMA automático dentro de muestra o en el set de prueba
# Generar pronóstico para el conjunto de prueba
forecast_arima_auto <- forecast(darima_auto, h = length(test_ts)) # Predecir los valores futuros
# Crear dataframe para gráfico interactivo del pronóstico
forecast_data_auto <- data.frame(Tiempo = time(forecast_arima_auto$mean),
Pronostico = as.numeric(forecast_arima_auto$mean),
Observado = as.numeric(test_ts))
# Graficar pronóstico junto con los valores observados reales
p4auto <- ggplot(forecast_data_auto, aes(x = Tiempo)) +
geom_line(aes(y = Pronostico, color = "Pronóstico")) +
geom_line(aes(y = Observado, color = "Observado")) +
ggtitle("Grafico 16. Pronóstico vs Observado") +
xlab("Tiempo") + ylab("variable1")
ggplotly(p4auto) # Convertir el gráfico en interactivo
Se observa que el modelo ARIMA pronostica una estabilidad en la demanda de consumo de energía de las grandes empresas industriales y comerciales (mercado no regulado) del Valle del Cauca, mientras que en los datos reales muestra una caída pronunciada en ese mismo periodo. Se capturan levemente los puntos de quiebre. En cuanto a la precisión, el modelo subestima la caída observada. Se recomienda realizar análisis con modelo SARIMA para mejorar el pronóstico.
Pronóstico automático dentro del set de prueba como tabla
# Cargar librerías necesarias
library(forecast)
library(dplyr)
# Generar pronóstico con el modelo ARIMA identificado
arima_forecast_auto <- forecast(auto_arima_model_no_seasonal, h = length(test_ts))
# Crear un dataframe con los valores observados y pronosticados
forecast_table_auto <- data.frame(
Tiempo = time(arima_forecast_auto$mean), # Extraer las fechas del pronóstico
Observado = as.numeric(test_ts), # Valores reales
Pronosticado = as.numeric(arima_forecast_auto$mean) # Valores pronosticados
)
# Mostrar la tabla
print(forecast_table_auto)
## Tiempo Observado Pronosticado
## 1 2024.750 238.68 235.2772
## 2 2024.833 232.39 235.2201
## 3 2024.917 228.59 235.2930
Ahora pronosticamos con el modelo automatico fuera del periodo de análisis, es decir enero 2025
Es decir, le sumamos al periodo de prueb auna observación más. Es decir, se estan pronosticando 4 observaciones o trimestres.
# Cargar librerías necesarias
library(forecast)
# Hacer un pronóstico para el siguiente trimestre (1 período adicional)
next_forecast_auto <- forecast(auto_arima_model_no_seasonal, h = length(test_ts) + 1)
# Extraer el pronóstico del próximo trimestre
next_month_forecast_auto <- data.frame(
Tiempo = time(next_forecast_auto$mean), # Extraer la fecha del pronóstico
Pronostico = as.numeric(next_forecast_auto$mean) # Valor pronosticado
)
# Mostrar el pronóstico completo
print(next_month_forecast_auto)
## Tiempo Pronostico
## 1 2024.750 235.2772
## 2 2024.833 235.2201
## 3 2024.917 235.2930
## 4 2025.000 235.4067
# Extraer solo el valor del trimestre adicional (último de la tabla)
next_month <- tail(next_month_forecast_auto, 1)
print(paste("Pronóstico para enero 2025:", next_month$Tiempo, "=", next_month$Pronostico))
## [1] "Pronóstico para enero 2025: 2025 = 235.406655300068"
Este modelo podria ser una solución o mejora al modelo arima tradicional ya que recoge el efecto estacional de las variables, es recomendable por tanto para datos que si tienen un componente estacional fuerte.
El modelo ajustado en este ejemplo es un SARIMA(0,1,1)(1,0,0)[12], lo que significa:
(0,1,1): Parte ARIMA no estacional: 0 términos autorregresivos (AR). 1 diferenciación (d), lo que indica que la serie fue diferenciada una vez para hacerla estacionaria. 1 término de media móvil (MA).
(1,0,0)[12]: Parte estacional con periodicidad 12 (mensual si los datos son mensuales): 1 término autorregresivo estacional (SAR). 0 diferenciaciones estacionales. 0 términos de media móvil estacionales (SMA).
El modelo SARIMA(0,1,1)(1,0,0)[12] sugiere que:
Identificación automática del modelo SARIMA
# Identificación automática modelo SARIMA
auto_arima_model <- auto.arima(train_ts) # Busca automáticamente los mejores parámetros del modelo ARIMA
print(auto_arima_model)
## Series: train_ts
## ARIMA(1,1,1)(0,0,2)[12] with drift
##
## Coefficients:
## ar1 ma1 sma1 sma2 drift
## 0.1871 -0.8273 0.2757 -0.0066 0.1657
## s.e. 0.1337 0.0909 0.0856 0.0756 0.2587
##
## sigma^2 = 139.5: log likelihood = -577.97
## AIC=1167.94 AICc=1168.51 BIC=1186.08
A continuación, se crea el objeto darima para luegO poder graficar los valores reales y observados:
# Cargar el paquete necesario
library(forecast)
# Ajustar el modelo SARIMA(0,1,1)(1,0,0)[12] #Modelo identificado en el paso anterior
darima <- Arima(train_ts,
order = c(0, 1, 1), # (p,d,q) -> (0,1,1)
seasonal = list(order = c(1, 0, 0), # (P,D,Q) -> (1,0,0)
period = 12)) # Periodicidad estacional de 12 meses
# Mostrar resumen del modelo ajustado
summary(darima)
## Series: train_ts
## ARIMA(0,1,1)(1,0,0)[12]
##
## Coefficients:
## ma1 sar1
## -0.7051 0.3002
## s.e. 0.0704 0.0769
##
## sigma^2 = 138.4: log likelihood = -578.97
## AIC=1163.94 AICc=1164.1 BIC=1173.01
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 0.5448704 11.64554 7.688524 -0.01349381 3.491692 0.7289233
## ACF1
## Training set 0.05307708
Validación de residuales del modelo automatico SARIMA
En el correlograma de residuos siguiente se observa que, mejora la correlación de los residuos frente a los dos modelos anteriores. Sin embargo, al comparar los valores reales VS pronosticados se determina coincidencia en algunos valores.
# Diagnóstico del modelo (los residuos deben ser ruido blanco)
checkresiduals(darima) # Verificar si los residuos son aleatorios y no presentan patrones
##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,1,1)(1,0,0)[12]
## Q* = 28.385, df = 22, p-value = 0.1633
##
## Model df: 2. Total lags used: 24
Evaluación de los residuos del modelo ARIMA
En la gráfica de la serie temporal de los residuos se observa que estos parecen relativamente centrados alrededor de 0 a excepción del año 2019- 2020 registrando valores atipicos de -25 y-75 por situación de pandemia.
La gráfica ACF de los residuos, muestra que la mayoría de los puntos están dentro de las bandas azules, mostrando ausencia de autocorrelación significativa.
El histograma de los residuos, es aproximadamente simétrica y centrada en cero, lo que indica una distribución cercana a la normal.
Pronóstico con el modelo SARIMA dentro del set de prueba-Gráfico líneas
# Generar pronóstico para el conjunto de prueba
forecast_arima <- forecast(darima, h = length(test_ts)) # Predecir los valores futuros
# Crear dataframe para gráfico interactivo del pronóstico
forecast_data <- data.frame(Tiempo = time(forecast_arima$mean),
Pronostico = as.numeric(forecast_arima$mean),
Observado = as.numeric(test_ts))
# Graficar pronóstico junto con los valores observados reales
p4 <- ggplot(forecast_data, aes(x = Tiempo)) +
geom_line(aes(y = Pronostico, color = "Pronóstico")) +
geom_line(aes(y = Observado, color = "Observado")) +
ggtitle("Grafico 17. Pronóstico vs Observado") +
xlab("Tiempo") + ylab("Unidad Variable 1")
ggplotly(p4) # Convertir el gráfico en interactivo
Se observa que el modelo SARIMA comparado con el anterior, muestra de forma clara la dirección general de la tendencia: tanto la línea pronosticada como la observada muestran un comportamiento descendente a lo largo de los últimos meses del año. Este comportamiento es coherente con la estacionalidad anual lo cual se observa en la extracción de señales indicadas anteriormente, donde típicamente se registra una reducción del consumo energético hacia el final del año.
Pronóstico del modelo automático SARIMA en el set de prueba-Tabla
# Cargar librerías necesarias
library(forecast)
library(dplyr)
# Generar pronóstico con el modelo ARIMA identificado
arima_forecast <- forecast(auto_arima_model, h = length(test_ts))
# Crear un dataframe con los valores observados y pronosticados
forecast_table <- data.frame(
Tiempo = time(arima_forecast$mean), # Extraer las fechas del pronóstico
Observado = as.numeric(test_ts), # Valores reales
Pronosticado = as.numeric(arima_forecast$mean) # Valores pronosticados
)
# Mostrar la tabla
print(forecast_table)
## Tiempo Observado Pronosticado
## 1 2024.750 238.68 234.1569
## 2 2024.833 232.39 232.3025
## 3 2024.917 228.59 230.5032
Pronóstico del modelo automático SARIMA fuera de muestra, es decir, en enero 2025
Es decir, le sumamos al periodo de prueba una observación más. Es decir, se estan pronosticando 4 observaciones o meses.
# Cargar librerías necesarias
library(forecast)
# Hacer un pronóstico para el siguiente mes (1 período adicional)
next_forecast <- forecast(auto_arima_model, h = length(test_ts) + 1)
# Extraer el pronóstico del próximo mes
next_month_forecast <- data.frame(
Tiempo = time(next_forecast$mean), # Extraer la fecha del pronóstico
Pronostico = as.numeric(next_forecast$mean) # Valor pronosticado
)
# Mostrar el pronóstico completo
print(next_month_forecast)
## Tiempo Pronostico
## 1 2024.750 234.1569
## 2 2024.833 232.3025
## 3 2024.917 230.5032
## 4 2025.000 234.5352
# Extraer solo el valor del trimestre adicional (último de la tabla)
next_month <- tail(next_month_forecast, 1)
print(paste("Pronóstico para enero 2025:", next_month$Tiempo, "=", next_month$Pronostico))
## [1] "Pronóstico para enero 2025: 2025 = 234.535184736333"
Dado el resultado anterior, el pronóstico para enero 2025 fue de 234.535 GWH de Consumo de energía de las grandes empresas industriales y comerciales (mercado no regulado) del Valle.
Algunas implicaciones para Emcali
• Una reducción en la demanda de energía puede generar una sobreoferta, lo que ocasiona ineficiencias operativas al no aprovechar completamente la infraestructura disponible y aumentar los costos por unidad producida.
• Ante esta situación, EMCALI debería revisar sus compras de energía en el mercado mayorista, evitando contratos de largo plazo con volúmenes elevados si no hay una demanda que los justifique. Esto permitiría mayor flexibilidad y reduciría riesgos financieros.
Algunas Recomendaciones Estratégicas para EMCALI
El modelo automático SARIMA fue el que mejor desempeño mostró en la comparación entre los datos reales y los pronosticados dentro del periodo de prueba (oct.nov.dic2024). Destacó por su mayor precisión en la captura de la dirección general de la tenndencia, lo que lo hace el más confiable.
No obstante, al analizar los residuos de los modelos, se identifican posibles áreas de mejora para robustecer los pronósticos, se observa que en la la grafica “serie de residuos en el tiempo” en general, los residuos parecen relativamente centrados alrededor de 0 a ecepción del año 2019- 2020 registrando valores de -25 y-75 situación de pandemia.or otra parte se observa en el ACF (Autocorrelación de los residuos) que algunos registros se salen del rango o limites de significancia lo que puede indicar que hay dependencia estacional residual no explicada. Los Histogramas muestran una distribución normal.