MANUELITA AZÚCAR Y ENERGÍA

1. INTRODUCCIÓN: SECTOR ECONOMICO Y CONTEXTUALIZACIÓN DE LA EMPRESA

El sector agroindustrial de los ingenios representa uno de los pilares productivos más importantes de la economía agrícola de Colombia, en especial del Valle del Cauca. Su aporte a la generación de empleo, a las exportaciones e integración a la cadena de valor de otras industrias, hacen que sea un sector fundamental en el ámbito económico. Los ingenios transforman la caña de azúcar en una amplia gama de productos como azúcar refinada, cruda, azúcares especiales, mieles, bioetanol, energía renovable, bagazo, vinaza y otros subproductos con aplicaciones en diversas industrias tales como farmacéutica, energética, alimentaria y agrícola. Se destacan por tener una circularidad en sus procesos donde intentan no desperdiciar ningún derivado de su proceso productivo; algunos ingenios ya lo hacen en su totalidad, como lo es Manuelita S.A. Además, se trata de un sector altamente tecnificado, que combina diversos procesos y cuya competitividad depende de factores como la productividad del cultivo, los costos de los insumos, las condiciones meteorológicas, la eficiencia en la logística y la dinámica de los precios internacionales y nacionales. Además, el sector presenta retos importantes donde la necesidad de avanzar hacia prácticas sostenibles y la diversificación del portafolio son elementos clave para la evolución del negocio. Dentro de todo este contexto, empresas como Manuelita, Incauca, Riopaila, Providencia, Mayagüez y demás, desempeñan un papel fundamental del sector. En este específico caso, Manuelita aporta desde la innovación, la exportación, la sostenibilidad y el valor agregado del negocio de la caña de azúcar.

Con 161 años de trayectoria, Manuelita se ha consolidado como una organización agroindustrial diversificada en los sectores de alimentos y energía renovable, con operaciones en varias zonas productivas de las Américas. La compañía produce alimentos de valor agregado y alta calidad, bajo un enfoque de sostenibilidad que contribuye al progreso y bienestar de las regiones donde opera. Actualmente, Manuelita cuenta con cuatro plataformas de negocio: Azúcar y Energía, Aceites, Frutas y Hortalizas, y Acuicultura, presentes en Colombia, Perú y Chile.

ANALISTAS

El siguiente equipo de trabajo evaluará la dinámica del sector agroindustrial y su impacto en “Manuelita Azúcar y Energía”, identificando patrones de evolución y cómo afectan a la organización, interactuando con tres variables (índice de precios al consumidor, tasa de ocupación laboral y tasa de desempleo), ademas de realizar la extracción de señales clave para evaluar y analizar tendencias, estacionalidades y cambios estructurales. Usando el modelo ARIMA pronosticaremos la variable del Indice de precios al consumidor (IPC) para asi lograr anticipar posibles impactos y sugerir acciones basadas en los hallazgos para la empresa y/o actores del sector.


Juan Manuel Jiménez


José Miguel Silva

Variable 1: IPC

El Índice de Precios al Consumidor (IPC) es una variable fundamental para analizar a Manuelita, ya que la inflación afecta de manera directa los costos de producción agrícolas e industriales, en especial los insumos como servicios logísticos, mantenimiento de equipos, empaques, combustibles, fertilizantes y demás. En un ingenio como Manuelita, donde gran parte del proceso depende de insumos que son altamente sensibles a los precios. Las variaciones en el IPC determinan la presión que se pone sobre los costos operativos y que, por consiguiente, afectan a la rentabilidad del negocio. Además,la inflación influye directamente en el precio final del azúcar y sus derivados, puesto que la compañía debe decidir si absorbe esos costos o se los traslada al consumidor (precios). En conclusión, un IPC elevado reduce el poder adquisitivo de los hogares en Colombia, lo que se puede traducir con un ajuste a la demanda de algunos productos de la empresa. Ver Figura 1.

# Convertir/declarar variable 1=INDICE PRECIOS CONSUMIDOR en serie de tiempo mensual
variable1_ts <- ts(data_col$IPC, start = c(2012, 1), frequency = 12)

Variable 2: Tasa de ocupación laboral

La tasa de ocupación laboral es importante para evaluar el desempeño de Manuelita ya que refleja la cantidad de personas que están empleadas y así se puede evaluar el nivel de ingreso disponible para consumo de bienes básicos y procesados. Dado que el azúcar no es solamente para consumo de hogar sino que también es un insumo fundamental para la industria alimentaria, una mayor ocupación del mercado laboral tiende a impulsar la actividad entre sectores y por ende, la demanda industrial de azúcar. Asimismo, un mercado laboral dinámico indica una mayor estabilidad económica. lo que ayuda al consumo de productos con valor agregado como el azúcar orgánica, las mezclas y edulcorantes que ofrece la compañía y por supuesto, su último lanzamiento de empaque 100% en papel. Finalmente, la tasa de ocupación afecta de igual forma a la competencia por la mano de obra especializada lo que hace un impacto en los costos y disponibilidad de personal.

# Convertir/declarar el TASA OCUPACION en serie de tiempo  mensual
variable2_ts <- ts(data_col$TO, start = c(2012, 1), frequency = 12)

Variable 3: Tasa de desempleo

En cuanto a la tasa de desempleo, esta es una variable macroeconómica vital para comprender el contexto en el que opera la empresa, ya que afecta tanto el nivel de consumo como los costos laborales del sector. Un aumento del desempleo reduce el ingreso de los hogares y por ende, la demanda por alimentos baja; aunque el azúcar refinado mantiene una demanda estable relativamente, los derivados o líneas diferenciadas pueden verse afectada. Además, Manuelita se caracteriza por ser el azúcar de mayor precio a consumidor entre todos sus competidores, esto se debe a la calidad y pureza de su producto, por lo que esto puede afectar incluso la demanda por el azúcar refinado. Desde la perspectiva de producción, un desempleo elevado incrementa la disponibilidad de mano de obra agrícola y de planta, facilitando así, la contratación. Por el contrario, un desempleo bajo, genera presión sobre salarios y dificulta la obtención de mano de obra especializada. Por su influencia sobre ambas esferas (producción y consumo), el desempleo es un indicador vital para anticipar cambios en los costos, estrategias y ventas.

# Convertir/declarar TASA DESEMPLEO en serie de tiempo mensual
variable3_ts <- ts(data_col$TD, start = c(2012, 1), frequency = 12)

2. METODOLOGÍA:

La metodología que utilizaremos para el análisis de “Manuelita Azucar y Energia” es la selección estrategica de variables previamente, en nuestro caso optamos por observar el comportamiento del Índice de Precios al consumidor, la tasa de ocupacion laboral y la tasa de desempleo, asi mismo procedemos a relacionar cada una de estas variables que son macroeconomicas, con la empresa que seleccionamos; asi procedemos a desglosar el comportamiento de cada variable en una serie de tiempo (ene-2012 a dic-2024) y a descomponerlas para evidenciar la serie original, la estacionalidad, el residuo y la tendencia.

Los modelos que utilizaremos para pronosticar la variable de IPC son:

ARIMA (AutoRegressive Integrated Moving Average) es un modelo para series temporales que combina componentes autorregresivos (AR), de diferenciación (I) y de medias móviles (MA) para capturar patrones no estacionales.

SARIMA (Seasonal ARIMA) es una extensión de ARIMA que incluye términos estacionales adicionales, permitiendo modelar series que presentan patrones que se repiten regularmente (por ejemplo, cada mes o cada año).

3. RESULTADOS

3.1 EXTRACCIÓN DE SEÑALES

Gráfico inicial de la variable 1 en niveles -Original

library(ggplot2)
library(plotly)

# Convertir la serie temporal a un vector numérico para lograr graficar con ggplot2
data_col$variable1 <- as.numeric(variable1_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 = variable1)) +
  geom_line(color = "grey", linewidth = 0.4) +  # Cambiado 'size' por 'linewidth'
  geom_point(color = "black", size = 0.1) +
  ggtitle("Figura 1: IPC: Serie original") +
  xlab("Tiempo") +
  ylab("Unidad Variable 1") +
  theme_minimal()

ggplotly(grafico_serie)

3.1.1 Extracción señales variable 1

# Cargar librerías necesarias
library(ggplot2)
library(plotly)

# Descomposición de la serie temporal
stl_decomp_var1 <- stl(variable1_ts, 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 (son 4 componentes)
  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 = "Figura 2:Descomposición temporal de la variable 1",
       x = "Tiempo",
       y = "Valor")

# Convertir a gráfico interactivo con plotly
ggplotly(p)

ANALISIS DE COMPONENTES EXTRAÍDOS VARIABLE IPC:

ESTACIONALIDAD:

La estacionalidad del IPC presenta variaciones regulares que observamos, se repiten cada año, con oscilaciones mensuales que rondan entre +0.3 y -0.3 puntos sobre el promedio. Esto significa que hay meses donde el IPC tiende a subir ligeramente, posiblemente por temporadas como inicio de año, matriculas, fin de año, demás y otros meses donde tiende a disminuir o estabilizarse. Para Manuelita, comprender estas oscilaciones es útil dado que durante meses con incrementos estacionales del IPC, los costos logísticos o ciertos insumos pueden encarecerse y la demanda al consumidor puede retraerse, afectando ventas y márgenes.Ver Figura 5.

RESIDUO:

El residuo del IPC muestra fluctuaciones irregulares con valores que oscilan entre los -0.5 y +0.5, aunque en algunos momentos toca picos de hasta +1.0 o -1.0, lo que refleja algunos choques inesperados en la inflación. Estos cambios no siguen un patrón y pueden estar relacionados con eventos coyunturales, como variaciones abruptas del dólar, ajustes regulatorios, crisis sanitarias y demás. Para la compañía Manuelita, estos residuos representan riesgos económicos de corto plazo porque pueden producir incrementos repentinos en costos, por lo que Manuelita debe tener planes de contingencia para evitar verse muy afectada ante estos cambios abruptos.

TENDENCIA:

La tendencia de la gráfica del IPC muestra un crecimiento sostenido y progresivo a lo largo de todo el periodo analizado. El nivel de la serie que contempla desde 2012 a 2024, pasa desde valores cercanos a los 80 en los primeros años a más de 130 hacia 2024-2025, lo que indica que la inflación ha crecido en los últimos años. Este comportamiento indica que tras una década, el nivel general de precios prácticamente se duplicó. Para Manuelita, esta tendencia al alza implica que los costos de producción también han venido aumentando de manera sostenida. Asimismo, un IPC creciente reduce progresivamente el poder adquisitivo de los consumidores, lo que puede afectar la demanda de productos como el azúcar y sus derivados. Ver Figura 8.

3.1.2 Extracción señales variable 2

# Cargar librerías necesarias
library(ggplot2)
library(plotly)

# 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
  Value = c(stl_decomp_var2$time.series[, "seasonal"], 
            stl_decomp_var2$time.series[, "trend"], 
            stl_decomp_var2$time.series[, "remainder"], 
            variable2_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 = "Figura 3: Descomposición temporal de la variable 2",
       x = "Tiempo",
       y = "Valor")

# Convertir a gráfico interactivo con plotly
ggplotly(p)

ANALISIS DE COMPONENTES EXTRAÍDOS VARIABLE TASA OCUPACIÓN LABORAL:

ESTACIONALIDAD:

La estacionalidad de la tasa de ocupación evidencia oscilaciones recurrentes que se mueven entre -1.0 y +1.2 puntos porcentuales, evidenciando que hay patrones repetitivos cada año. Existen algunos meses donde la ocupación sube, y esto puede pasar por ciclos agrícolas, temporadas comerciales o contrataciones temporales. Para Manuelita, estas oscilaciones pueden anticipar meses donde los consumidores cuentan con mayor estabilidad laboral, lo que ayuda a la demanda y consumo de bienes básicos, frente a meses donde se reduce la demanda por la disminución de la actividad laboral.Ver Figura 6.

RESIDUO:

En lo que respecta al residuo de la tasa de ocupación, se evidencian fluctuaciones suaves entre -0.5 y +0.5, pero muestra un evento atípico fuerte rondando el 2020, donde cae cerca de -6 puntos, representando el choque laboral que hubo por la crisis del COVID 19. Este comportamiento refleja impactos inesperados como crisis sanitarias o económicas. En el caso de Manuelita, estos movimientos pueden afectar la disponibilidad de mano de obra o el nivel de compra de los consumidores en el corto plazo, lo que obliga a tener planes comerciales de contingencia.

TENDENCIA:

En cuanto a la tendencia de la tasa de ocupación se mantiene relativamente estable entre 58% y 60% durante la mayor parte del periodo 2013-2019, sin embargo, presenta una caída importante alrededor de 2020, donde baja hasta 51%, coincidiendo con la crisis sanitaria por la pandemia del COVID-19. Luego, la tendencia se va recuperando de manera gradual, regresando a niveles de 57% y 58% en 2024. Para Manuelita, esta dinámica es importante considerarla, ya que una mayor tasa de ocupación implica un mercado laboral activo y que tiene una mayor capacidad de consumo. Por ende, podría haber pasado que con la caída en 2020 haya sucedido un periodo donde la demanda de productos como el azúcar pudo haberse reducido, afectando directamente las ventas y canales. Ver Figura 9.

3.1.3 Extracción señales variable 3

# Cargar librerías necesarias
library(ggplot2)
library(plotly)

# 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 = "Figura 4: Descomposición temporal de la variable 3",
       x = "Tiempo",
       y = "Valor")

# Convertir a gráfico interactivo con plotly
ggplotly(p)

ANALISIS DE COMPONENTES EXTRAÍDOS VARIABLE TASA DESEMPLEO:

ESTACIONALIDAD:

La estacionalidad de la tasa de desempleo presenta oscilaciones claras y recurrentes entre -1.0 y +2.0 puntos porcentuales, lo que nos indica que hay meses donde el desempleo tiende a incrementarse sistemáticamente, posiblemente por contratos temporales que finalizan, ciclos académicos o cierres de la actividad económica. Para Manuelita, reconocer estos patrones permite anticipar periodos del año donde los consumidores podrían tener mayor o menor estabilidad laboral, influyendo en su comportamiento de compra. Asimismo, podría dar señales de cuando hay periodos en los que tal vez haya mayor oferta laboral y asimismo, menores costos de nómina. Ver Figura 7.

RESIDUO:

El residuo de la tasa de desempleo evidencia variaciones entre -1 y+1 típicas, sin embargo, presenta un pico atípico pronunciado alrededor de 2020, cuando llega aproximadamente a +5 puntos, lo que confirma un choque externo muy fuerte que no puede explicarse por tendencia ni estacionalidad. Este salto importante coincide con las pérdidas masivas de empleos en la pandemia. Para la compañía, estos residuos pueden representar factores no esperados que afectan la planificación de ventas, la operación y otros procesos ya que generan cambios bruscos en el consumo y en la disponibilidad de la mano de obra para los procesos agrícolas y logísticos.

TENDENCIA:

La tendencia de la tasa de desempleo se ha mantenido en niveles relativamente estables entre 9% y 11% desde 2013 hasta 2019, mostrando un comportamiento moderado. No obstante, a partir de 2020 se ha observado un aumento abrupto que lleva la tasa a niveles máximos cerca de 16%, reflejando el fuerte deterioro que ha tenido el mercado laboral durante la pandemia. Después de este suceso, la tendencia baja de manera progresiva, retornando a niveles de 11 y 12% en años posteriores. Para la compañía esto es fundamental tenerlo en consideración ya que esto disminuye la demanda interna y puede afectarse la rotación de productos del portafolio debido a la reducción de poder adquisitivo de los hogares. Ver Figura 10.

Después de la descomposición temporal de cada variable, se extrae la variable ajustada por estacionalidad para graficarla junto con la serie original:

Se crea la variable1 ajustada por estacionalidad

# Extraer los componentes de la descomposición
variable1_sa <- variable1_ts - stl_decomp_var1$time.series[, "seasonal"]

Se crea la variable2 ajustada por estacionalidad

# Extraer los componentes de la descomposición
variable2_sa <- variable2_ts - stl_decomp_var2$time.series[, "seasonal"]

Se crea la variable3 ajustada por estacionalidad

# Extraer los componentes de la descomposición
variable3_sa <- variable3_ts - stl_decomp_var3$time.series[, "seasonal"]

Ahora si se puede graficar las series originales versus la ajustada por estacionalidad

3.2 RESULTADOS: S. ORIGINAL VS S. AJUSTADA

3.2.1 Gráfico serie original VS ajustada Variable 1

# 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("Figura 5: IPC (VAR1) :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)

3.2.2 Gráfico serie original VS ajustada Variable 2

# 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("Figura 6: TASA DE OCUPACIÓN (VAR2): 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)

3.2.3 Gráfico serie original VS ajustada Variable 3

# 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("Figura 7: TASA DE DESEMPLEO (VAR3): 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)

Ahora graficamos serie original vs tendencia

Primero se debe obtener la tendencia de cada variable y luego graficarla

Tendencia Variable 1

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("Figura 8: IPC: 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)

Tendencia Variable 2

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("Figura 9: Tasa Ocupación Laboral: 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)

Tendencia Variable 3

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("Figura 10: Tasa de desempleo: 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)

Ahora calculamos la tasa de crecimiento de la serie original vs tendencia:

Tasa de crecimiento de la serie de tendencia y original para la variable 1

#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 original y tendencia 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("Figura 11: IPC: 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)

Ahora calculamos la tasa de crecimiento de la serie original vs tendencia: variable 2

#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 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("Figura 12: Tasa Ocupación: 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)

Ahora calculamos la tasa de crecimiento de la serie original vs tendencia: variable 3

#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 de la tasa de crecimiento anual variable 2
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("Figura 13: Tasa de desempleo: 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)

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.

Modelo ARIMA

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

Modelo ARIMA automático normal (sin tener en cuenta el factor estacional)

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(2,2,1) 
## 
## Coefficients:
##          ar1      ar2      ma1
##       0.8153  -0.2195  -0.9082
## s.e.  0.0949   0.0861   0.0622
## 
## sigma^2 = 0.0801:  log likelihood = -22.47
## AIC=52.94   AICc=53.21   BIC=65.01
## 
## Training set error measures:
##                      ME      RMSE       MAE        MPE      MAPE       MASE
## Training set 0.01061054 0.2783565 0.2042477 0.01040633 0.1984684 0.03786293
##                      ACF1
## Training set -0.008880447

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.815306   0.094904   8.5908  < 2e-16 ***
## ar2 -0.219452   0.086113  -2.5484  0.01082 *  
## ma1 -0.908227   0.062167 -14.6094  < 2e-16 ***
## ---
## 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(2, 2, 1))  # Especificamos directamente (p=4, d=1, q=2)  

# Mostrar resumen del modelo ajustado
summary(darima_auto)
## Series: train_ts 
## ARIMA(2,2,1) 
## 
## Coefficients:
##          ar1      ar2      ma1
##       0.8153  -0.2195  -0.9082
## s.e.  0.0949   0.0861   0.0622
## 
## sigma^2 = 0.0801:  log likelihood = -22.47
## AIC=52.94   AICc=53.21   BIC=65.01
## 
## Training set error measures:
##                      ME      RMSE       MAE        MPE      MAPE       MASE
## Training set 0.01061054 0.2783565 0.2042477 0.01040633 0.1984684 0.03786293
##                      ACF1
## Training set -0.008880447

Validación de residuales o errores del modelo

Figura 14: Validación de residuales

# 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(2,2,1)
## Q* = 58.905, df = 21, p-value = 1.868e-05
## 
## Model df: 3.   Total lags used: 24

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 15: Pronóstico vs Observado") +
  xlab("Tiempo") + ylab("variable1")

ggplotly(p4auto)  # Convertir el gráfico en interactivo

Interpretación modelo automatico (2,2,1):El modelo automático (2,2,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    143.83     144.5871
## 2 2024.833    144.22     145.2544
## 3 2024.917    144.88     145.9558

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   144.5871
## 2 2024.833   145.2544
## 3 2024.917   145.9558
## 4 2025.000   146.6630
# 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 = 146.662959097937"

Modelo SARIMA automático

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.

Parte no estacional (1,1,2):

1 término autorregresivo (AR).

1 diferenciación (d), lo que indica que la serie fue diferenciada una vez para volverla estacionaria.

2 términos de media móvil (MA).

Parte estacional (0,1,1)[12]: periodicidad 12

0 términos autorregresivos estacionales (SAR).

1 diferenciación estacional (D).

1 término de media móvil estacional (SMA).

Interpretación general del modelo:

La serie presenta una tendencia no estacionaria que se corrige con la diferenciación no estacional.

El comportamiento actual depende tanto de valores pasados (AR(1)) como de errores pasados (MA(2)).

Existe una estructura estacional marcada, corregida mediante una diferenciación estacional y un componente SMA(1) que captura dependencias a 12 períodos.

El modelo ofrece un ajuste adecuado según criterios de información como AIC y BIC, aunque siempre es recomendable compararlo con modelos alternativos para garantizar la mejor capacidad predictiva.

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,2)(0,1,1)[12] 
## 
## Coefficients:
##          ar1      ma1      ma2     sma1
##       0.9537  -0.3101  -0.2039  -0.8243
## s.e.  0.0352   0.0895   0.0866   0.0866
## 
## sigma^2 = 0.05467:  log likelihood = 0.72
## AIC=8.57   AICc=9.01   BIC=23.27

A continuación, se crea el objeto Sarima para luegO poder graficar los valores reales y observados:

# Cargar el paquete necesario
library(forecast)

# Ajustar el modelo SARIMA(1,1,2)(0,1,1)[12] #Modelo identificado en el paso anterior
darima <- Arima(train_ts, 
                order = c(1, 1, 2),  # (p,d,q) -> (0,1,1)
                seasonal = list(order = c(0, 1, 1),  # (P,D,Q) -> (1,0,0)
                                period = 12))  # Periodicidad estacional de 12 meses

# Mostrar resumen del modelo ajustado
summary(darima)
## Series: train_ts 
## ARIMA(1,1,2)(0,1,1)[12] 
## 
## Coefficients:
##          ar1      ma1      ma2     sma1
##       0.9537  -0.3101  -0.2039  -0.8243
## s.e.  0.0352   0.0895   0.0866   0.0866
## 
## sigma^2 = 0.05467:  log likelihood = 0.72
## AIC=8.57   AICc=9.01   BIC=23.27
## 
## Training set error measures:
##                      ME      RMSE       MAE        MPE      MAPE       MASE
## Training set 0.01550025 0.2204357 0.1555902 0.01633994 0.1502826 0.02884292
##                    ACF1
## Training set 0.01873309

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. Funcionando mejor el modelo SARIMA (1,1,2)(0,1,1)

Figura 16: Validación de residuales SARIMA

# 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,2)(0,1,1)[12]
## Q* = 21.057, df = 20, p-value = 0.3938
## 
## Model df: 4.   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("Pronóstico vs Observado") +
  xlab("Tiempo") + ylab("Unidad Variable 1")

ggplotly(p4)  # Convertir el gráfico en interactivo

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    143.83     144.2030
## 2 2024.833    144.22     144.4865
## 3 2024.917    144.88     145.0330

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   144.2030
## 2 2024.833   144.4865
## 3 2024.917   145.0330
## 4 2025.000   146.0644
# 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 = 146.064423028787"

MODELO UTILIZADO:

El modelo automático SARIMA(1,1,2)(0,0,1) 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 los puntos de quiebre, lo que lo hace el más confiable.

COMPARACION PRONOSTICO SARIMA VS DATOS REALES DANE 2025:

“Pronóstico para enero 2025: 2025 = 146.064423028787”

Figura 17: Total, Índice de Precios al Consumidor (IPC) Fuente: DANE

DECISIONES A TOMAR BASADAS EN LAS SEÑALES EXTRAIDAS )

En base a las señales extraidas:

  1. La serie del IPC entre 2012 y 2024 muestra una tendencia creciente, una estacionalidad moderada y residuos que reflejan choques inesperados; en conjunto, esto indica que los precios y costos de producción han aumentado de forma sostenida, existen meses con variaciones previsibles y otros con volatilidad temporal. Para Manuelita, este comportamiento sugiere decisiones como ajustar periódicamente los precios para compensar la inflación, planificar inventarios y compras anticipadas en meses de aumentos estacionales, optimizar costos logísticos, y diseñar estrategias de cobertura o contingencia frente a choques inesperados que puedan afectar márgenes y demanda.

  2. La tasa de ocupación se mantiene estable entre 2013 y 2019, cae fuertemente en 2020 por la pandemia y luego se recupera gradualmente hasta 2024; además, presenta oscilaciones estacionales anuales moderadas y un residuo con un choque atípico en 2020. En conjunto, esto indica que la capacidad de consumo del mercado depende tanto de cambios estructurales como de variaciones regulares y eventos inesperados. Para Manuelita, las decisiones clave incluyen ajustar estrategias comerciales en periodos de menor ocupación, anticipar la demanda en meses de mayor actividad laboral, fortalecer la planificación ante choques económicos y sanitarios, y diseñar acciones de mercado flexibles que acompañen la recuperación o caída del empleo.7

  3. La tasa de desempleo se mantuvo estable entre 2013 y 2019, subió de forma abrupta hasta cerca de 16% en 2020 por la pandemia y luego descendió gradualmente hacia niveles de 11–12%, mostrando también una estacionalidad marcada con variaciones anuales regulares y un residuo con un choque atípico en 2020. En conjunto, esto evidencia que el mercado laboral experimenta cambios estructurales, ciclos previsibles y eventos inesperados que afectan el poder adquisitivo y la dinámica productiva. Con base en ello, Manuelita puede tomar decisiones como ajustar proyecciones de demanda según el deterioro o mejora del empleo, preparar estrategias comerciales y promociones en meses de mayor desempleo, optimizar la planificación de mano de obra en periodos con mayor oferta laboral y establecer planes de contingencia para choques externos que impacten tanto el consumo como la operación agrícola y logística.

ESTRATEGIAS Y ACCIONES EMPRESARIALES CON BASE AL PRONOSTICO DEL IPC: (CORTO PLAZO)

A partir de las señales extraídas del análisis de tendencia, estacionalidad y variabilidad inesperada de las tres variables macroeconómicas, Manuelita S.A. puede tomar decisiones estratégicas orientadas a anticipar riesgos y optimizar su operación. En primer lugar, la tendencia inflacionaria al alza sugiere la necesidad de fortalecer la estrategia de cobertura de costos, como negociación anticipada de insumos, diversificación de proveedores y contratos a precio fijo para mitigar el impacto del IPC sobre los gastos operacionales. La estacionalidad observada en la ocupación y el desempleo permite planificar la producción y campañas comerciales en meses donde los hogares tienen mayor estabilidad laboral, ajustando inventarios y esfuerzos de venta según la capacidad de consumo. Por otro lado, los choques residuales significan que la empresa debe implementar mecanismos de flexibilidad operativa, como reservas financieras, incrementos temporales en inventarios críticos o planes de respuesta rápida ante cambios abruptos del mercado laboral. En conjunto, estas decisiones permiten a la empresa no solo proteger su rentabilidad en entornos volátiles, sino también aprovechar oportunidades surgidas de ciclos estacionales y momentos de mayor demanda interna.