En el presente informe se realiza un análisis del sector cementero en Colombia, tomando como caso de estudio a la empresa Cementos Argos y examinando su comportamiento en relación con tres variables clave para el seguimiento de la actividad productiva y la dinámica del sector:
Cementos Argos es una compañía multinacional con más de noventa años de trayectoria, que ha logrado consolidar su presencia en 16 países y territorios, tanto en economías emergentes como desarrolladas. Actualmente es la cementera y concretera líder en Colombia y una de las empresas más destacadas del sector en Centroamérica y el Caribe, gracias a su capacidad productiva, su estrategia de expansión y su papel fundamental en el desarrollo de la infraestructura regional.
El análisis de estas variables permite comprender no solo la evolución del desempeño operativo de la empresa, sino también las tendencias del mercado del cemento, el comportamiento de la demanda en el sector de la construcción y las condiciones macroeconómicas que influyen en la actividad edificadora del país.
Para el desarrollo de este informe, indicialmente se instalaron las librerias necesarias y se cargó la base de datos que contiene registros desde el año 2012 a 2024.
Para el desarrollo de este informe, se inicia con un paso indispensable, el cual consiste en declarar las variables como serie temporales, con este paso se establece:
Sin esta información, el modelo no puede diferenciar tendencia, estacionalidad o irregularidades.
Muchas series de tiempo están influenciadas simultáneamente por distintos factores. Por eso, separar la tendencia, la estacionalidad y el componente aleatorio es fundamental para entender qué impulsa realmente los cambios en los datos.
Por ejemplo, al analizar variables del sector como la producción de cemento (toneladas), los despachos de cemento (toneladas) o las licencias de construcción aprobadas (m²), resulta clave identificar si los aumentos o disminuciones se deben a una tendencia estructural o a patrones estacionales propios del sector.
Separar estos componentes también mejora el desempeño de los modelos de pronóstico. Si eliminamos la estacionalidad de los despachos mensuales de cemento, el modelo puede enfocarse en la tendencia real del mercado y producir predicciones más precisas sobre la demanda futura.
Además, la descomposición facilita detectar comportamientos inusuales. Por ejemplo, si la producción de cemento presenta una caída abrupta que no corresponde a patrones históricos de estacionalidad, esto podría indicar un fenómeno relevante: menor actividad constructora, crisis a nivel mundial, choques en oferta, dificultades logísticas o cambios regulatorios.
En resumen, la descomposición de series de tiempo ayuda a interpretar mejor la evolución del sector, mejora la precisión de los pronósticos y permite tomar decisiones estratégicas más informadas. Es una herramienta esencial en analítica económica e industrial, especialmente en actividades donde las fluctuaciones del mercado pueden impactar inversiones, proyecciones de demanda y planificación operativa.
Para el desarrollo de la extracción de señales previamente se declararon las tres variables en serie de tiempo mensuales.
Gráfico inicial de la variable PNCEM en niveles - Original
En la Figura 1, se observa que desde 2012 hasta 2019 hay una tendencia ascendente en la producción de cemento, apesar de que la serie presenta variaciones mensuales, el comportamiento general muestra un crecimiento sostenido en el nivel de producción.Esto es típico en sectores industriales donde la demanda y capacidad productiva aumentan gradualmente.
La gráfica tiene picos y caídas frecuentes, lo cual indica una alta variabilidad mes a mes y posibles patrones estacionales (subidas y bajadas recurrentes por época del año), esto justifica el uso posterior de descomposición y ajuste estacional.
El comportamiento de la producción de cemento en Colombia está directamentamente relacionada a los ingresos de la compañía ya que es su actividad princiapal, considerando que Argos abarca el 43% de la producción nacional, se puede deducir la gran afectación que tuvo la empresa en el año 2020 por la redcción ocasionada por el fenomeno de la pandemia. Tras el desplome de 2020, la serie muestra una recuperación fuerte y relativamente rápida.
library(ggplot2)
library(plotly)
# Convertir la serie temporal a un vector numérico para lograr graficar con ggplot2
data_col$variablePNCEM <- as.numeric(variablePNCEM_ts)
# Crear el gráfico
grafico_serie <- ggplot(data_col, aes(x = seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = nrow(data_col)),
y = variablePNCEM)) +
geom_line(color = "green", linewidth = 0.4) + # Cambiado 'size' por 'linewidth'
geom_point(color = "black", size = 0.1) +
ggtitle("Figura 1. Serie Original: PRODUCCION DE CEMENTO - PNCEM") +
xlab("Fecha") +
ylab("Toneladas") +
theme_minimal()
ggplotly(grafico_serie)
Extracción señales variable PNCEM
# Cargar librerías necesarias
library(ggplot2)
library(plotly)
# Descomposición de la serie temporal
stl_decomp_varPNCEM <- stl(variablePNCEM_ts, s.window = "periodic")
# Convertir la descomposición a un data frame para graficar con ggplot2
stl_df_varPNCEM <- data.frame(
Time = rep(time(variablePNCEM_ts), 4), # Tiempo repetido para cada componente (son 4 componentes)
Value = c(stl_decomp_varPNCEM$time.series[, "seasonal"],
stl_decomp_varPNCEM$time.series[, "trend"],
stl_decomp_varPNCEM$time.series[, "remainder"],
variablePNCEM_ts),
Component = rep(c("Estacional", "Tendencia", "Residuo", "Serie Original"), each = length(variablePNCEM_ts))
)
# Crear gráfico con ggplot2
p <- ggplot(stl_df_varPNCEM, aes(x = Time, y = Value, color = Component)) +
geom_line() +
facet_wrap(~Component, scales = "free_y", ncol = 1) +
theme_minimal() +
labs(title = "Figura 2. Descomposición temporal de la variable PNCEM",
x = "Fecha",
y = "Valor")
# Convertir a gráfico interactivo con plotly
ggplotly(p)
Respecto a la Figura 2:
Gráfico inicial de la variable DECEM en niveles - Original
De acuerdo con la Figura 3, se eviendia que tiene un comportamiento similar al de la producción de cemento, comparten los mismos hitos económicos: crecimiento lento, choque fuerte en 2020 y recuperación posterior.
La producción es un indicador de oferta, mientras que el despacho refleja más directamente la demanda del mercado del cemento.
Las diferencias en la volatilidad sugieren que, aunque se produzca de manera estable, el despacho depende más de dinámicas del sector construcción, incluidas las licencias de construcción aprobadas.
library(ggplot2)
library(plotly)
# Convertir la serie temporal a un vector numérico para lograr graficar con ggplot2
data_col$variableDECEM <- as.numeric(variableDECEM_ts)
# Crear el gráfico
grafico_serie <- ggplot(data_col, aes(x = seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = nrow(data_col)),
y = variableDECEM)) +
geom_line(color = "green", linewidth = 0.4) + # Cambiado 'size' por 'linewidth'
geom_point(color = "black", size = 0.1) +
ggtitle("Figura 3. Serie Original: DESPACHO DE CEMENTO - DECEM") +
xlab("Fecha") +
ylab("Toneladas") +
theme_minimal()
ggplotly(grafico_serie)
Extracción señales variable DESPACHO DE CEMENTO - DECEM
Conforme la extracción de señales del Despacho de Cemento, en la Figura 4 se observan picos y caídas similares en los mismos meses, lo que indica que el despacho de cemento es una actividad altamente estacional, la tendencia evidencia ciclos económicos claros, con fases de expansión y contracción y los residuos permanecen cerca de cero, lo que indica un buen ajuste de los componentes tendencia + estacionalidad, sin embargo, aparece un punto atípico muy fuerte alrededor de 2020, donde el residuo cae abruptamente.
# Cargar librerías necesarias
library(ggplot2)
library(plotly)
# Descomposición de la serie temporal
stl_decomp_varDECEM <- stl(variableDECEM_ts, s.window = "periodic")
# Convertir la descomposición a un data frame para graficar con ggplot2
stl_df_varDECEM <- data.frame(
Time = rep(time(variableDECEM_ts), 4), # Tiempo repetido para cada componente
Value = c(stl_decomp_varDECEM$time.series[, "seasonal"],
stl_decomp_varDECEM$time.series[, "trend"],
stl_decomp_varDECEM$time.series[, "remainder"],
variableDECEM_ts),
Component = rep(c("Estacional", "Tendencia", "Residuo", "Serie Original"), each = length(variableDECEM_ts))
)
# Crear gráfico con ggplot2
p <- ggplot(stl_df_varDECEM, aes(x = Time, y = Value, color = Component)) +
geom_line() +
facet_wrap(~Component, scales = "free_y", ncol = 1) +
theme_minimal() +
labs(title = "Figura 4. Descomposición temporal de la variable DECEM",
x = "Fecha",
y = "Valor")
# Convertir a gráfico interactivo con plotly
ggplotly(p)
Gráfico inicial de la variable LICC en niveles - Original
En la Figura 5, se muestra el comportamiento de las licencias de construcción aprobadas en m2, y a simple vista, no parece haber una tendencia claramente creciente o decreciente en todo el período. La serie fluctúa alrededor de un nivel promedio cercano a 1.5–2.2 millones de m², con puntos puntuales de valores muy altos. Además, se evidencia a partir del 2023 una reducción de licencias, esto posiblemente por la reducción de los subsidios de vivienda en el país.
En la Cementera Argos, las licencias de construcción son un indicador adelantado que anticipa la actividad constructora y, por tanto, ayudan a prever el comportamiento futuro de la producción de cemento. Aunque no siempre se mueven al mismo ritmo por factores coyunturales, ambas variables están estrechamente vinculadas dentro del ciclo de inversión en construcción y vivienda.
La relación no es perfecta. Puede haber desalineamientos por:
library(ggplot2)
library(plotly)
# Convertir la serie temporal a un vector numérico para lograr graficar con ggplot2
data_col$variableLICC <- as.numeric(variableLICC_ts)
# Crear el gráfico
grafico_serie <- ggplot(data_col, aes(x = seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = nrow(data_col)),
y = variableLICC)) +
geom_line(color = "green", linewidth = 0.4) + # Cambiado 'size' por 'linewidth'
geom_point(color = "black", size = 0.1) +
ggtitle("Figura 5. Serie Original: LICENCIAS DE CONSTRUCCIÓN APROBADAS EN COLOMBIA - LICC") +
xlab("Fecha") +
ylab("m2") +
theme_minimal()
ggplotly(grafico_serie)
Extracción señales variable LICENCIAS DE CONSTRUCCIÓN EN COLOMBIA - LICC
A continuación, se presenta la Figura 6, en la cual se puede evidenciar que la estacionalidad es fuerte, recurrente y muy regular, los picos estacionales aparecen aproximadamente con periodicidad anual, reflejando meses del año en los que, históricamente, se aprueban más licencias.La amplitud del patrón estacional es considerable, con oscilaciones de hasta 700.000 m², lo que indica que los ciclos intraanuales explican una parte importante del comportamiento de la serie.
La tendencia refleja ciclos económicos claros en el sector construcción: expansión (2012–2015), ajuste (2016–2019), choque exógeno (2020), recuperación (2021–2022) y nuevo descenso (2023–2024).
El residuo presenta alta variabilidad, lo cual indica que la serie contiene movimientos no explicados completamente por la estacionalidad ni la tendencia.
# Cargar librerías necesarias
library(ggplot2)
library(plotly)
# Descomposición de la serie temporal
stl_decomp_varLICC <- stl(variableLICC_ts, s.window = "periodic")
# Convertir la descomposición a un data frame para graficar con ggplot2
stl_df_varLICC <- data.frame(
Time = rep(time(variableLICC_ts), 4), # Tiempo repetido para cada componente
Value = c(stl_decomp_varLICC$time.series[, "seasonal"],
stl_decomp_varLICC$time.series[, "trend"],
stl_decomp_varLICC$time.series[, "remainder"],
variableLICC_ts),
Component = rep(c("Estacional", "Tendencia", "Residuo", "Serie Original"), each = length(variableLICC_ts))
)
# Crear gráfico con ggplot2
p <- ggplot(stl_df_varLICC, aes(x = Time, y = Value, color = Component)) +
geom_line() +
facet_wrap(~Component, scales = "free_y", ncol = 1) +
theme_minimal() +
labs(title = "Figura 6. Descomposición temporal de la variable LICC",
x = "Fecha",
y = "Valor")
# Convertir a gráfico interactivo con plotly
ggplotly(p)
Después de la descomposición temporal de cada variable, se extrae la variable ajustada por estacionalidad para graficarla junto con la serie original:
Después de realizar la descomposición temporal de cada variable, se obtiene la versión ajustada por estacionalidad. Esta serie representa el comportamiento de la variable sin los patrones estacionales recurrentes.
Una vez extraída, se puede graficar junto con la serie original para comparar cómo se comporta la variable antes y después de remover la estacionalidad. Esto permite visualizar con mayor claridad la tendencia real y las fluctuaciones estructurales, eliminando las variaciones que se repiten periódicamente.
Gráficos de las series originales vs la ajustada por estacionalidad
Gráfico serie original VS ajustada Variable PNCEM
La figura 7 presenta la serie original (línea azul) y la serie ajustada por estacionalidad (línea verde) de la producción de cemento en Colombia. Esta comparación permite identificar el comportamiento subyacente de la variable, eliminando los efectos recurrentes o predecibles asociados a los ciclos estacionales.
# Crear vector de fechas correctamente alineado con la serie
fechas_varPNCEM <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variablePNCEM_ts))
# Gráfico mejorado con fechas en el eje X
grafico_ajustada_varPNCEM <- ggplot() +
geom_line(aes(x = fechas_varPNCEM, y = variablePNCEM_ts), color = "green", size = 0.5, linetype = "solid", name = "Serie Original") +
geom_line(aes(x = fechas_varPNCEM, y = variablePNCEM_sa), color = "blue", size = 0.6, linetype = "solid", name = "Serie Ajustada") +
ggtitle("Figura 7. PNCEM: Serie Original vs Serie Ajustada por Estacionalidad") +
xlab("Fecha") +
ylab("Toneladas") +
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_varPNCEM)
Gráfico serie original VS ajustada Variable DECEM
Conforme la Figura 8, se puede observar que la serie ajustada por estacionalidad sigue muy de cerca la tendencia general de la original, sin embargo:
# Crear vector de fechas correctamente alineado con la serie
fechas_varDECEM <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variableDECEM_ts))
# Gráfico mejorado con fechas en el eje X
grafico_ajustada_varDECEM <- ggplot() +
geom_line(aes(x = fechas_varDECEM, y = variableDECEM_ts), color = "green", size = 0.5, linetype = "solid", name = "Serie Original") +
geom_line(aes(x = fechas_varDECEM, y = variableDECEM_sa), color = "blue", size = 0.6, linetype = "solid", name = "Serie Ajustada") +
ggtitle("Figura 8. DECEM: Serie Original vs Serie Ajustada por Estacionalidad") +
xlab("Fecha") +
ylab("Toneladas") +
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_varDECEM)
Gráfico serie original VS ajustada Variable LICC
En la Figura 9, se puede decir que La serie ajustada suaviza estos picos y permite ver que las variaciones extremas suelen ser eventos puntuales y no una tendencia estructural.
# Crear vector de fechas correctamente alineado con la serie
fechas_varLICC <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variableLICC_ts))
# Gráfico mejorado con fechas en el eje X
grafico_ajustada_varLICC <- ggplot() +
geom_line(aes(x = fechas_varLICC, y = variableLICC_ts), color = "green", size = 0.5, linetype = "solid", name = "Serie Original") +
geom_line(aes(x = fechas_varLICC, y = variableLICC_sa), color = "blue", size = 0.6, linetype = "solid", name = "Serie Ajustada") +
ggtitle("Figura 9. LICC:Serie Original vs Serie Ajustada por Estacionalidad") +
xlab("Fecha") +
ylab("m2 aprobados") +
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_varLICC)
Serie original vs tendencia
Se procede a graficar la serie original junto con su componente de tendencia, con el fin de visualizar cómo evoluciona el comportamiento subyacente de largo plazo frente a las fluctuaciones observadas en los datos reales, para esto, primero se obtiene la tendencia de cada variable y luego se grafica.
Tendencia Variable PRODUCCION NACIONAL DE CEMENTO - PNCEM
En la Figura 10, se puede observar que mientras la serie original de la producción de cemento en Colombia muestra fluctuaciones mensuales importantes, la tendencia suavizada permite identificar su comportamiento estructural. Entre 2012 y 2013 se observa una ligera caída, seguida de una recuperación y un período de crecimiento sostenido entre 2015 y 2018. Luego la tendencia se estabiliza y cae abruptamente en 2020, reflejado por la pandemia. A partir de ese punto, la serie se recupera con fuerza durante 2021–2022, aunque hacia 2023–2025 vuelve a mostrar una leve desaceleración. En conjunto, el indicador presenta ciclos claros de caída, expansión, crisis y recuperación.
library(ggplot2)
library(plotly)
# Convertir la serie a un vector numérico
variablePNCEM_vec <- as.numeric(variablePNCEM_ts)
tendencia_varPNCEM <- as.numeric(stl_decomp_varPNCEM$time.series[, "trend"])
# Asegurar que 'fechas' tenga la misma longitud
fechas <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variablePNCEM_ts))
# Gráfico interactivo de la serie original vs tendencia
grafico_tendencia_varPNCEM <- ggplot() +
geom_line(aes(x = fechas, y = variablePNCEM_vec, color = "Serie Original"), size = 0.7, linetype = "solid") +
geom_line(aes(x = fechas, y = tendencia_varPNCEM, color = "Tendencia"), size = 0.8, linetype = "solid") +
scale_color_manual(values = c("Serie Original" = "green", "Tendencia" = "purple")) +
ggtitle(" Figura 10. PNCEM: Serie Original vs Tendencia") +
xlab("Fecha") +
ylab("Tonealadas") +
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_varPNCEM)
Tendencia Variable DESPACHO DE CEMENTO - DECEM
En la Figura 11, se puede observa un comportamiento similar a la Figura 10, esto debido a la relación directa que existe entre la producción y el despacho de cemento.
library(ggplot2)
library(plotly)
# Convertir la serie a un vector numérico
variableDECEM_vec <- as.numeric(variableDECEM_ts)
tendencia_varDECEM <- as.numeric(stl_decomp_varDECEM$time.series[, "trend"])
# Asegurar que 'fechas' tenga la misma longitud
fechas <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variableDECEM_ts))
# Gráfico interactivo de la serie original vs tendencia
grafico_tendencia_varDECEM <- ggplot() +
geom_line(aes(x = fechas, y = variableDECEM_vec, color = "Serie Original"), size = 0.7, linetype = "solid") +
geom_line(aes(x = fechas, y = tendencia_varDECEM, color = "Tendencia"), size = 0.8, linetype = "solid") +
scale_color_manual(values = c("Serie Original" = "green", "Tendencia" = "purple")) +
ggtitle("Figura 11. DECEM: Serie Original vs Tendencia") +
xlab("Fecha") +
ylab("Toneladas") +
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_varDECEM)
Tendencia Variable LICENCIAS DE CONSTRUCCIÓN EN COLOMBIA LICC
A continuación se muestra la tendencia VS la serie original del comprotamiento de las licencias de construcción en Colombia entre 2012 y 2025. Se observa un comportamiento cíclico, con fases claras de expansión y contracción. La tendencia suavizada revela el patrón estructural:
La serie original (línea verde) muestra una alta volatilidad mensual, con picos y caídas bruscas que reflejan fluctuaciones de corto plazo del mercado y de la aprobación de licencias. En contraste, la línea de tendencia (morado) suaviza estas variaciones y permite identificar el comportamiento de fondo, eliminando ruido y revelando los ciclos principales.
library(ggplot2)
library(plotly)
# Convertir la serie a un vector numérico
variableLICC_vec <- as.numeric(variableLICC_ts)
tendencia_varLICC <- as.numeric(stl_decomp_varLICC$time.series[, "trend"])
# Asegurar que 'fechas' tenga la misma longitud
fechas <- seq.Date(from = as.Date("2012-01-01"), by = "month", length.out = length(variableLICC_ts))
# Gráfico interactivo de la serie original vs tendencia
grafico_tendencia_varLICC <- ggplot() +
geom_line(aes(x = fechas, y = variableLICC_vec, color = "Serie Original"), size = 0.7, linetype = "solid") +
geom_line(aes(x = fechas, y = tendencia_varLICC, color = "Tendencia"), size = 0.8, linetype = "solid") +
scale_color_manual(values = c("Serie Original" = "green", "Tendencia" = "purple")) +
ggtitle("Figura 12. LICC: Serie Original vs Tendencia") +
xlab("Fecha") +
ylab("m2") +
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_varLICC)
Tasa de crecimiento de la serie original vs tendencia:
Analizar tasas de crecimiento permite ver el comportamiento dinámico de la serie, comparar períodos, captar choques y recuperaciones, y entender mejor los ciclos económicos.
Mientras los valores absolutos son útiles para medir el tamaño, las tasas revelan la velocidad y dirección del cambio.
En las Figuras 13, 14 y 15 se observa un comportamiento muy similar: Tras el desplome de 2020, se registra un salto extraordinario de más del 300% en la serie origina, este efecto se genera por el efecto base: la recuperación se compara con un año extremadamente bajo, después del rebote, las tasas se normalizan, el cual es un proceso de retorno a niveles normales. La tendencia registra un aumento positivo más moderado, confirmando la recuperación del nivel, pero sin exagerar el impacto transitorio.
Tasa de crecimiento de la serie de tendencia y original para la variable PNCEM
## [1] 144
## [1] 144
## [1] 144
*Gráfico variable original y tendencia variable PNCEM: tasa de crecimiento anual**
library(ggplot2)
library(plotly)
# Gráfico de la tasa de crecimiento anual variable PNCEM
grafico_crecimiento_varPNCEM <- ggplot() +
geom_line(aes(x = fechas_corregidas_varPNCEM, y = tasa_crecimiento_varPNCEM), color = "green", size = 0.7) +
geom_line(aes(x = fechas_corregidas_varPNCEM, y = tasa_tendencia_varPNCEM), color = "purple", size = 0.8, linetype = "dashed") +
ggtitle("Figura 13. PNCEM: Tasa de crecimiento anual % de la serie Original y la tendencia") +
xlab("Fecha") +
ylab("% de Crecimiento Anual") +
theme_minimal()
# Convertir a gráfico interactivo
ggplotly(grafico_crecimiento_varPNCEM)
Ahora calculamos la tasa de crecimiento de la serie original vs tendencia: variable DECEM
## [1] 144
## [1] 144
## [1] 144
# Gráfico de la tasa de crecimiento anual variable DECEM
grafico_crecimiento_varDECEM <- ggplot() +
geom_line(aes(x = fechas_corregidas_varDECEM, y = tasa_crecimiento_varDECEM), color = "green", size = 0.7) +
geom_line(aes(x = fechas_corregidas_varDECEM, y = tasa_tendencia_varDECEM), color = "purple", size = 0.8, linetype = "dashed") +
ggtitle("Figura 14. DECEM: Tasa de crecimiento anual % de la serie Original y la Tendencia") +
xlab("Fecha") +
ylab("% de Crecimiento Anual") +
theme_minimal()
# Convertir a gráfico interactivo
ggplotly(grafico_crecimiento_varDECEM)
Ahora calculamos la tasa de crecimiento de la serie original vs tendencia: variable LICC
## [1] 144
## [1] 144
## [1] 144
# Gráfico de la tasa de crecimiento anual variable LICC
grafico_crecimiento_varLICC <- ggplot() +
geom_line(aes(x = fechas_corregidas_varLICC, y = tasa_crecimiento_varLICC), color = "green", size = 0.7) +
geom_line(aes(x = fechas_corregidas_varLICC, y = tasa_tendencia_varLICC), color = "purple", size = 0.8, linetype = "dashed") +
ggtitle("Figura 15. LICC: Tasa de crecimiento anual % de la serie Original y la tendencia") +
xlab("Fecha") +
ylab("% de Crecimiento Anual") +
theme_minimal()
# Convertir a gráfico interactivo
ggplotly(grafico_crecimiento_varLICC)
Analizar la tasa de crecimiento anual ayuda a detectar cambios en el entorno económico que afectan el sector. Se pueden prever crisis o períodos de auge y prepararse para ellos.
División en conjunto de entrenamiento y prueba para la variable PNCEM que es la elegida para pronosticar
El código siguiente divide una serie temporal (variablePNCEM_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(variablePNCEM_ts) - 3 # Se deja fuera los últimos 3 valores para usarlos como set de prueba.
train_ts <- window(variablePNCEM_ts, end = c(2024, 9)) # Entrenamiento hasta septiembre 2024
test_ts <- window(variablePNCEM_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)
##
## Coefficients:
## ar1 ma1
## 0.3336 -0.8940
## s.e. 0.0957 0.0472
##
## sigma^2 = 1.13e+10: log likelihood = -1974.44
## AIC=3954.88 AICc=3955.04 BIC=3963.95
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 10449.67 105259.9 72659.69 -1.566531 8.971488 0.9023438
## ACF1
## Training set -0.03433432
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.333617 0.095680 3.4868 0.0004888 ***
## ma1 -0.893984 0.047222 -18.9315 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Ajuste del modelo ARIMA(1,1,1) 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(1, 1, 1)) # Especificamos directamente (p=1, d=1, q=1)
# Mostrar resumen del modelo ajustado
summary(darima_auto)
## Series: train_ts
## ARIMA(1,1,1)
##
## Coefficients:
## ar1 ma1
## 0.3336 -0.8940
## s.e. 0.0957 0.0472
##
## sigma^2 = 1.13e+10: log likelihood = -1974.44
## AIC=3954.88 AICc=3955.04 BIC=3963.95
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 10449.67 105259.9 72659.69 -1.566531 8.971488 0.9023438
## ACF1
## Training set -0.03433432
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(1,1,1)
## Q* = 45.196, df = 22, p-value = 0.002506
##
## Model df: 2. Total lags used: 24
Al analizar los residuos del modelo ARIMA(1,1,1), podemos evaluar qué tan bien se ajusta el modelo a los datos. La gráfica de los residuos muestra que estos se mantienen alrededor de cero y no siguen un patrón fijo, lo cual indica que el modelo logra capturar la mayor parte del comportamiento de la serie. Sin embargo, aparece un valor atípico marcado en el año 2020, relacionado con el impacto económico que causó la pandemia.
La gráfica de autocorrelación (ACF) evidencia que casi todos los valores están dentro de los límites aceptables, lo que significa que los residuos no muestran dependencia entre sí.
En el histograma de los residuos se aprecia que su distribución es más o menos simétrica alrededor de cero, aunque con algunas variaciones en los extremos. Esto indica que no se ajustan perfectamente a una distribución normal, pero estas diferencias no afectan de manera importante la utilidad del modelo, especialmente para realizar pronósticos.
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("Figura 16. Pronóstico vs Observado") +
xlab("Fecha") + ylab("Toneladas PNCEM")
ggplotly(p4auto) # Convertir el gráfico en interactivo
La gráfica compara los valores que el modelo proyectó para la producción de cemento con los valores que realmente ocurrieron durante el periodo analizado.
En primer lugar, se observa que la línea correspondiente al pronóstico (color celeste) se mantiene relativamente estable. Esto significa que el modelo esperaba que la producción no mostrara grandes variaciones en esos meses, sino que se mantuviera dentro de un rango similar al que venía mostrando anteriormente.
Sin embargo, al contrastar esta proyección con la línea de los valores reales (color rojo), se aprecia un comportamiento mucho más variable. La producción real muestra primero una disminución pronunciada y luego una recuperación considerable. Estos movimientos bruscos no fueron anticipados por el modelo, lo que sugiere que durante ese periodo ocurrieron factores o eventos que alteraron la producción y que no estaban reflejados en la información histórica utilizada para generar el pronóstico. En términos generales, al comparar ambas líneas, se observa que el modelo no logra capturar adecuadamente el punto de quiebre. Esto se refleja particularmente en el mes de octubre, donde el modelo subestima de manera considerable el valor real registrado.
Interpretación modelo automatico (1,1,1):El modelo automático (1,1,1) parece pronosticar mejor dentro de prueba. Hay un sobre ajuste, pero se capturan muy bien los puntos de quiebre. Es un modelo tentativo adecuado para pronpostico fuera de muestra o a futuro.
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 1180815 1133340
## 2 2024.833 1121219 1141154
## 3 2024.917 1145357 1143761
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 1133340
## 2 2024.833 1141154
## 3 2024.917 1143761
## 4 2025.000 1144631
# 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 = 1144630.62871857"
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 dautomá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,1)[12]
##
## Coefficients:
## ar1 ma1 sma1
## 0.3748 -0.9184 0.3120
## s.e. 0.0966 0.0477 0.0782
##
## sigma^2 = 1.02e+10: log likelihood = -1966.72
## AIC=3941.45 AICc=3941.72 BIC=3953.54
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(1,1,1)(0,0,1)[12] #Modelo identificado en el paso anterior
darima <- Arima(train_ts,
order = c(1, 1, 1), # (p,d,q) -> (1,1,1)
seasonal = list(order = c(0, 0, 1), # (P,D,Q) -> (0,0,1)
period = 12)) # Periodicidad estacional de 12 meses
# Mostrar resumen del modelo ajustado
summary(darima)
## Series: train_ts
## ARIMA(1,1,1)(0,0,1)[12]
##
## Coefficients:
## ar1 ma1 sma1
## 0.3748 -0.9184 0.3120
## s.e. 0.0966 0.0477 0.0782
##
## sigma^2 = 1.02e+10: log likelihood = -1966.72
## AIC=3941.45 AICc=3941.72 BIC=3953.54
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 9371.476 99667.25 67628.01 -1.49445 8.36446 0.8398565 -0.03621159
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 una poca coincidencia. Sigue funcionando mejor el modelo automatico (1,1,1)
Al examinar los residuos del modelo ARIMA(0,1,1)(1,0,0), se observa que estos se distribuyen de forma estable alrededor de cero, sin evidenciar tendencias persistentes ni ciclos que sugieran falta de ajuste. La mayoría de los valores se encuentran dentro de los límites de confianza, lo que sugiere que los errores no siguen una estructura temporal.
La forma de la distribución de los residuos es cercana a una curva normal, con ligeras desviaciones que no afectan de manera relevante la interpretación. Esto permite asumir que los errores son aleatorios y que el modelo tiene un buen comportamiento estadístico.
# 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(1,1,1)(0,0,1)[12]
## Q* = 15.553, df = 21, p-value = 0.7942
##
## Model df: 3. Total lags used: 24
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("Figura 17. Pronóstico vs Observado") +
xlab("Fecha") + ylab("Toneladas PNCEM")
ggplotly(p4) # Convertir el gráfico en interactivo
Ambas líneas siguen un patrón similar, caracterizado por una caída hacia el punto central del periodo y una recuperación posterior. Esta similitud indica que el modelo capturó adecuadamente el punto de quiebre y no subestima significativamente los valores reales.
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 1180815 1147233
## 2 2024.833 1121219 1117421
## 3 2024.917 1145357 1171977
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 1147233
## 2 2024.833 1117421
## 3 2024.917 1171977
## 4 2025.000 1101935
# 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 = 1101934.82625893"
Las toneladas proyectadas por el modelo para enero de 2025 son de 1.101.935, pero al compararlas con las cifras reales (946.304 toneladas), se observa una variación negativa del -14%, lo que evidencia una sobrestimación significativa por parte del modelo. Aunque el modelo contempló la persistencia de la desaceleración del sector y la caída del mes de enero productos de factores estacionales, económicos y operativos que afectan la demanda y la actividad constructiva en ese mes, no logró capturar completamente el impacto de varios factores externos que agravaron la caída en ese mes, entre ellos:
Estos elementos, en conjunto, acentuaron la estacionalidad típica de enero, mes que históricamente presenta menor actividad productiva, debido a:
Inicio de año fiscal y presupuestal: Muchas entidades públicas y privadas están en proceso de reorganización financiera, lo que retrasa la ejecución de obras y licitaciones.
Vacaciones colectivas y receso laboral: Enero coincide con el periodo de vacaciones en Colombia, lo que reduce la actividad en obras civiles, plantas de producción y transporte de materiales.
Baja inversión en infraestructura: El arranque lento de proyectos públicos y privados en enero limita la demanda de cemento, especialmente en sectores como vivienda social y vías.
Altas tasas de interés: En años recientes, el encarecimiento del crédito ha desincentivado nuevas construcciones, afectando directamente el consumo de cemento.
El pronóstico puede generar efectos significativos en la empresa desde tres perspectivas principales:
Gestión de inventarios: Una sobrestimación de la demanda puede provocar una acumulación innecesaria de insumos o productos terminados. Esto se traduce en mayores costos de almacenamiento, riesgo de obsolescencia y posibles pérdidas por deterioro. Además, impacta directamente el capital de trabajo, ya que inmoviliza recursos que podrían destinarse a otras áreas estratégicas.
Planeación operativa: Si el pronóstico proyecta una demanda mayor a la real, la empresa podría planear turnos adicionales, contratar más personal o activar procesos logísticos que finalmente no se requieren. Esto genera gastos operativos que no se recuperan y disminuye la eficiencia global de la operación, afectando indicadores como productividad y utilización de capacidad instalada.
Impacto financiero: La diferencia entre lo pronosticado y lo realmente ocurrido puede alterar el flujo de caja, reducir la rentabilidad esperada y afectar la planeación presupuestal. Un pronóstico impreciso también puede influir negativamente en decisiones de inversión o financiamiento, debido a que se toman con base en expectativas que no reflejan el comportamiento real del mercado.
Dado que la tendencia y la estacionalidad del modelo captan una caída en la producción de cemento a inicios de 2025 y una persistente desaceleración en la demanda, Cementos Argos puede adoptar estrategias enfocadas en eficiencia operativa, consolidación comercial y planificación sectorial. Estas acciones buscan mitigar los efectos de la menor demanda y garantizar sostenibilidad financiera y productiva.
Optimización operativa
• Ajuste de capacidad productiva: Reducir temporalmente los turnos o líneas de producción para evitar sobrecostos por capacidad ociosa.
• Mantenimiento preventivo estratégico: Aprovechar los periodos de baja demanda para realizar mantenimientos que aumenten la eficiencia futura.
• Control de inventarios: Implementar modelos just-in-time o revisar políticas de stock para evitar acumulación innecesaria de producto terminado.
Fortalecimiento comercial y de mercado
• Diversificación de clientes: Impulsar el programa Argos Hogar para autoconstrucción y remodelación, un segmento que suele ser más estable.
• Promociones y paquetes comerciales: Ofrecer descuentos por volumen, fidelización o alianzas con distribuidores para estimular compras.
• Expansión geográfica: Desarrollar convenios con alcaldías y empresas públicas para proyectos de mantenimiento vial o pequeñas obras urbanas.
Planificación estratégica
• Cementos Argos puede fortalecer su análisis estratégico siguiendo variables clave:
Licencias de construcción por departamento (DANE).
Ejecución de proyectos de infraestructura bajo el programa 5G.
Comportamiento de tasas de interés del Banco de la República.
Expectativas de inversión pública para 2025, especialmente en pavimentación y vivienda social.
• Alianzas público-privadas: Participar activamente en mesas sectoriales para influir en políticas que reactiven la inversión en infraestructura.
Participar activamente en cámaras y gremios como Camacol y el Consejo Colombiano de Construcción Sostenible.
Impulsar con gobiernos locales programas de mejoramiento de vías terciarias, parques y obras públicas donde el cemento es un insumo esencial.
Aportar estudios técnicos para facilitar financiación de proyectos de infraestructura regional.