Ejercicio 1

# Cargar librerías
library(forecast)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(tseries)
library(ggplot2)
library(readxl)


Mercado_laboral_y_población <- read_excel("Mercado laboral y población.xlsx")
head(Mercado_laboral_y_población)
## # A tibble: 6 × 3
##   Fecha      `Tasa de desempleo - total nacional` Tasa de ocupación - total na…¹
##   <chr>      <chr>                                <chr>                         
## 1 yyyy/mm/dd %                                    %                             
## 2 2001/01/31 16.62                                57.58                         
## 3 2001/02/28 17.43                                56.93                         
## 4 2001/03/31 15.81                                57.57                         
## 5 2001/04/30 14.52                                55.76                         
## 6 2001/05/31 14.04                                56.23                         
## # ℹ abbreviated name: ¹​`Tasa de ocupación - total nacional`
datos <- Mercado_laboral_y_población

# 2. LIMPIAR Y CONVERTIR A NUMÉRICO
# Verificar el tipo de datos
cat("Tipo de datos de la columna:", class(datos$`Tasa de desempleo - total nacional`), "\n")
## Tipo de datos de la columna: character
# Convertir explícitamente a numérico y eliminar NA
valores_desempleo <- as.numeric(as.character(datos$`Tasa de desempleo - total nacional`))
## Warning: NAs introduced by coercion
valores_desempleo <- valores_desempleo[!is.na(valores_desempleo)]

cat("Número de valores NA:", sum(is.na(valores_desempleo)), "\n")
## Número de valores NA: 0
cat("Longitud de la serie limpia:", length(valores_desempleo), "\n")
## Longitud de la serie limpia: 295
# 3. CREAR SERIE TEMPORAL NUMÉRICA
desempleo_ts <- ts(valores_desempleo, 
                   start = c(2001, 1),
                   frequency = 12)

# a) GRÁFICO DE LA SERIE
plot(desempleo_ts, main = "Tasa de Desempleo Colombia (2001-2025)",
     xlab = "Año", ylab = "Tasa de Desempleo (%)", col = "blue", lwd = 2)
grid()

# b) PRUEBA DE ESTACIONARIEDAD (ADF)
adf_test <- adf.test(desempleo_ts)
cat("\nPRUEBA ADF - Tasa de Desempleo:\n")
## 
## PRUEBA ADF - Tasa de Desempleo:
cat("Dickey-Fuller =", round(adf_test$statistic, 4), "\n")
## Dickey-Fuller = -3.1324
cat("p-value =", adf_test$p.value, "\n")
## p-value = 0.09959869
if(adf_test$p.value > 0.05) {
  cat("CONCLUSIÓN: La serie NO es estacionaria (p > 0.05)\n")
  cat("Se requiere diferenciación para lograr estacionariedad\n")
} else {
  cat("CONCLUSIÓN: La serie es estacionaria (p < 0.05)\n")
}
## CONCLUSIÓN: La serie NO es estacionaria (p > 0.05)
## Se requiere diferenciación para lograr estacionariedad
# c) DIFERENCIACIÓN - VERSIÓN SEGURA
desempleo_diff <- diff(desempleo_ts, differences = 1)

# Si aún hay error, usar esta alternativa:
# desempleo_diff <- na.omit(diff(desempleo_ts, differences = 1))

# d) IDENTIFICACIÓN DEL MODELO - FAC y FACP
par(mfrow = c(1, 2))
acf(desempleo_diff, na.action = na.pass, main = "FAC - Serie Diferenciada", lag.max = 24)
pacf(desempleo_diff, na.action = na.pass, main = "FACP - Serie Diferenciada", lag.max = 24)

par(mfrow = c(1, 1))

# e) MODELO SARIMA AUTOMÁTICO
cat("\nAJUSTANDO MODELO SARIMA...\n")
## 
## AJUSTANDO MODELO SARIMA...
modelo <- auto.arima(desempleo_ts, seasonal = TRUE, stepwise = FALSE)
cat("\nMODELO SELECCIONADO:\n")
## 
## MODELO SELECCIONADO:
print(modelo)
## Series: desempleo_ts 
## ARIMA(1,0,0)(0,1,1)[12] with drift 
## 
## Coefficients:
##          ar1     sma1    drift
##       0.9211  -0.8870  -0.0137
## s.e.  0.0237   0.0517   0.0086
## 
## sigma^2 = 0.7017:  log likelihood = -359.73
## AIC=727.46   AICc=727.6   BIC=742.04
cat("\nRESUMEN DEL MODELO:\n")
## 
## RESUMEN DEL MODELO:
summary(modelo)
## Series: desempleo_ts 
## ARIMA(1,0,0)(0,1,1)[12] with drift 
## 
## Coefficients:
##          ar1     sma1    drift
##       0.9211  -0.8870  -0.0137
## s.e.  0.0237   0.0517   0.0086
## 
## sigma^2 = 0.7017:  log likelihood = -359.73
## AIC=727.46   AICc=727.6   BIC=742.04
## 
## Training set error measures:
##                       ME      RMSE       MAE        MPE    MAPE     MASE
## Training set -0.01746578 0.8161182 0.5289384 -0.4196927 4.45886 0.420831
##                  ACF1
## Training set -0.10771
# f) PRONÓSTICO (12 meses: Ago 2025 - Jul 2026)
pronostico <- forecast(modelo, h = 12)

# Gráfico del pronóstico
plot(pronostico, main = "Pronóstico Tasa de Desempleo (Ago 2025 - Jul 2026)",
     xlab = "Año", ylab = "Tasa de Desempleo (%)")
lines(desempleo_ts, col = "black", lwd = 2)
grid()

# g) TABLA DE PRONÓSTICOS
cat("\nPRONÓSTICO TASA DE DESEMPLEO (%):\n")
## 
## PRONÓSTICO TASA DE DESEMPLEO (%):
meses <- c("Ago-2025", "Sep-2025", "Oct-2025", "Nov-2025", "Dic-2025",
           "Ene-2026", "Feb-2026", "Mar-2026", "Abr-2026", "May-2026",
           "Jun-2026", "Jul-2026")

tabla_pronostico <- data.frame(
  Mes = meses,
  Pronostico = round(pronostico$mean, 2),
  Limite_Inferior_80 = round(pronostico$lower[,1], 2),
  Limite_Superior_80 = round(pronostico$upper[,1], 2),
  Limite_Inferior_95 = round(pronostico$lower[,2], 2),
  Limite_Superior_95 = round(pronostico$upper[,2], 2)
)

print(tabla_pronostico)
##         Mes Pronostico Limite_Inferior_80 Limite_Superior_80 Limite_Inferior_95
## 1  Ago-2025       8.34               7.27               9.42               6.70
## 2  Sep-2025       8.11               6.65               9.57               5.88
## 3  Oct-2025       7.73               6.00               9.45               5.09
## 4  Nov-2025       7.42               5.50               9.33               4.49
## 5  Dic-2025       8.04               5.97              10.10               4.88
## 6  Ene-2026      11.16               8.97              13.34               7.82
## 7  Feb-2026       9.99               7.71              12.27               6.51
## 8  Mar-2026       9.16               6.80              11.52               5.55
## 9  Abr-2026       9.50               7.08              11.92               5.79
## 10 May-2026       9.53               7.05              12.00               5.74
## 11 Jun-2026       9.14               6.62              11.66               5.28
## 12 Jul-2026       9.48               6.92              12.04               5.56
##    Limite_Superior_95
## 1                9.99
## 2               10.34
## 3               10.36
## 4               10.34
## 5               11.19
## 6               14.50
## 7               13.48
## 8               12.77
## 9               13.21
## 10              13.32
## 11              12.99
## 12              13.39
# h) VALIDACIÓN DEL MODELO
cat("\nVALIDACIÓN DEL MODELO:\n")
## 
## VALIDACIÓN DEL MODELO:
cat("Prueba de Ljung-Box para residuales:\n")
## Prueba de Ljung-Box para residuales:
checkresiduals(modelo)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(1,0,0)(0,1,1)[12] with drift
## Q* = 33.439, df = 22, p-value = 0.05595
## 
## Model df: 2.   Total lags used: 24
# i) ECUACIÓN DEL MODELO
cat("\nECUACIÓN DEL MODELO SARIMA:\n")
## 
## ECUACIÓN DEL MODELO SARIMA:
orden <- arimaorder(modelo)
cat("SARIMA(", orden[1], ",", orden[2], ",", orden[3], ")(",
    orden[4], ",", orden[5], ",", orden[6], ")[12]\n", sep = "")
## SARIMA(1,0,0)(0,1,1)[12]

Ejercicio 3

# Cargar librerías
library(forecast)
library(tseries)
library(ggplot2)
library(readxl)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
# Cargar datos
X3_BEER <- read_excel("3. BEER.xlsx")
head(X3_BEER)
## # A tibble: 6 × 2
##   Quarter  beer
##   <chr>   <dbl>
## 1 1956Q1   284.
## 2 1956Q2   213.
## 3 1956Q3   227.
## 4 1956Q4   308.
## 5 1957Q1   262 
## 6 1957Q2   228.
beer_data <- X3_BEER

# Convertir la columna Quarter a formato de fecha 
# Extraer año y trimestre
beer_data$Year <- as.numeric(substr(beer_data$Quarter, 1, 4))
beer_data$Qtr <- as.numeric(substr(beer_data$Quarter, 6, 6))

# Crear serie de tiempo (frecuencia = 4 para datos trimestrales)
beer_ts <- ts(beer_data$beer, start = c(1956, 1), frequency = 4)

# =============================================================================
# a) Gráfico de la serie de tiempo y descripción
# =============================================================================
plot(beer_ts, main = "Producción de Cerveza en Australia (1956-1994)",
     xlab = "Año", ylab = "Producción (megalitros)", col = "darkred", lwd = 2)
grid()

# 
# -----------------------------------------------------------------------------
# La serie muestra una clara TENDENCIA CRECIENTE a lo largo del tiempo y un
# PATRÓN ESTACIONAL MARCADO con picos consistentes en el cuarto trimestre de
# cada año. La producción ha aumentado desde aproximadamente 200 megalitros
# en 1956 hasta alrededor de 600 megalitros en 1994, con fluctuaciones
# estacionales predecibles.

# =============================================================================
# b) Evaluación de estacionalidad (seasonal graph) 
# =============================================================================
# Crear gráfico de cajas por trimestre
beer_data$Quarter_Factor <- factor(beer_data$Qtr, labels = c("Q1", "Q2", "Q3", "Q4"))
boxplot(beer ~ Quarter_Factor, data = beer_data, 
        main = "Producción por Trimestre",
        xlab = "Trimestre", ylab = "Producción (megalitros)",
        col = "lightblue")

# -----------------------------------------------------------------------------
# El gráfico de cajas por trimestre confirma un FUERTE PATRÓN ESTACIONAL.
# El cuarto trimestre (Q4) consistentemente presenta la producción más alta,
# seguido por el primer trimestre (Q1), mientras que el segundo y tercer
# trimestre (Q2 y Q3) muestran los niveles más bajos de producción.
# Esto refleja un comportamiento típico de consumo de cerveza con aumentos
# en periodos festivos.

# =============================================================================
# c) Prueba de estacionariedad (ADF)
# =============================================================================
adf_test <- adf.test(beer_ts)
## Warning in adf.test(beer_ts): p-value greater than printed p-value
print(adf_test)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  beer_ts
## Dickey-Fuller = 0.57302, Lag order = 5, p-value = 0.99
## alternative hypothesis: stationary
# Mostrar resultados de la prueba
if(adf_test$p.value > 0.05) {
  cat("La serie NO es estacionaria (p-value =", round(adf_test$p.value, 4), ")\n")
} else {
  cat("La serie es estacionaria (p-value =", round(adf_test$p.value, 4), ")\n")
}
## La serie NO es estacionaria (p-value = 0.99 )
# -----------------------------------------------------------------------------
# Resultado: p-value = 0.99
# Conclusión: La serie NO ES ESTACIONARIA (p-value > 0.05).
# La alta probabilidad indica que no podemos rechazar la hipótesis nula de
# que existe una raíz unitaria, confirmando la presencia de tendencia y
# estacionalidad en la serie.

# =============================================================================
# d) Identificación y estimación del modelo SARIMA
# =============================================================================
# Diferenciación estacional
beer_diff <- diff(beer_ts, differences = 1)
beer_seasonal_diff <- diff(beer_ts, lag = 4, differences = 1)

# FAC y FACP de la serie diferenciada
par(mfrow = c(1, 2))
acf(beer_seasonal_diff, na.action = na.pass, main = "FAC - Serie diferenciada")
pacf(beer_seasonal_diff, na.action = na.pass, main = "FACP - Serie diferenciada")

par(mfrow = c(1, 1))

# Ajustar modelo SARIMA automáticamente
model <- auto.arima(beer_ts, seasonal = TRUE, stepwise = FALSE, approximation = FALSE)
summary(model)
## Series: beer_ts 
## ARIMA(0,1,2)(0,1,1)[4] 
## 
## Coefficients:
##           ma1     ma2     sma1
##       -0.9852  0.4156  -0.7668
## s.e.   0.0793  0.0814   0.0548
## 
## sigma^2 = 256.8:  log likelihood = -625.32
## AIC=1258.64   AICc=1258.92   BIC=1270.66
## 
## Training set error measures:
##                      ME     RMSE      MAE         MPE     MAPE      MASE
## Training set -0.4291945 15.60433 11.74947 -0.09639846 2.818065 0.7130395
##                    ACF1
## Training set 0.02234089
# Mostrar ecuación del modelo
cat("\nEcuación del modelo SARIMA seleccionado:\n")
## 
## Ecuación del modelo SARIMA seleccionado:
cat("SARIMA", arimaorder(model), "\n")
## SARIMA 0 1 2 0 1 1 4
# Modelo estimado: ARIMA(0,1,2)(0,1,1)[4]

# Ecuación del modelo:
# (1 - B)(1 - B⁴)Yₜ = (1 - 0.9852B + 0.4156B²)(1 - 0.7668B⁴)εₜ

# Justificación del modelo:
# - DIFERENCIACIÓN REGULAR (d=1): Necesaria para eliminar la tendencia
# - DIFERENCIACIÓN ESTACIONAL (D=1): Necesaria para eliminar la estacionalidad anual
# - TÉRMINOS MA(2): Los coeficientes MA son significativos (ma1 = -0.9852, ma2 = 0.4156)
# - TÉRMINO SMA(1): El coeficiente estacional es significativo (sma1 = -0.7668)
# - BONDAD DE AJUSTE: AIC = 1258.64, BIC = 1270.66 (valores relativamente bajos)
# - PRECISIÓN: MAPE = 2.82% (error porcentual medio bajo)

# =============================================================================
# e) Pronóstico hasta Q4 1996 (10 periodos hacia adelante)
# =============================================================================
forecast_beer <- forecast(model, h = 10)

# Gráfica del pronóstico
plot(forecast_beer, main = "Pronóstico de Producción de Cerveza hasta Q4 1996",
     xlab = "Año", ylab = "Producción (megalitros)")
lines(beer_ts, col = "black", lwd = 2)
grid()

# Tabla de pronósticos
cat("\nPronóstico para 1994Q3 - 1996Q4:\n")
## 
## Pronóstico para 1994Q3 - 1996Q4:
forecast_values <- data.frame(
  Periodo = c("1994Q3", "1994Q4", "1995Q1", "1995Q2", "1995Q3", "1995Q4", 
              "1996Q1", "1996Q2", "1996Q3", "1996Q4"),
  Pronostico = round(forecast_beer$mean, 2),
  Lo_80 = round(forecast_beer$lower[,1], 2),
  Hi_80 = round(forecast_beer$upper[,1], 2),
  Lo_95 = round(forecast_beer$lower[,2], 2),
  Hi_95 = round(forecast_beer$upper[,2], 2)
)
print(forecast_values)
##    Periodo Pronostico  Lo_80  Hi_80  Lo_95  Hi_95
## 1   1994Q3     402.64 382.10 423.18 371.23 434.05
## 2   1994Q4     518.88 498.34 539.42 487.47 550.29
## 3   1995Q1     425.15 402.79 447.52 390.95 459.35
## 4   1995Q2     383.43 359.38 407.47 346.65 420.20
## 5   1995Q3     391.47 363.83 419.11 349.20 433.74
## 6   1995Q4     511.63 482.59 540.67 467.22 556.05
## 7   1996Q1     417.91 386.89 448.93 370.46 465.35
## 8   1996Q2     376.18 343.30 409.06 325.89 426.47
## 9   1996Q3     384.22 347.79 420.66 328.51 439.94
## 10  1996Q4     504.38 466.33 542.43 446.19 562.58
# Pronósticos principales:
# - 1996Q4: 504.38 megalitros (rango: 446.19 - 562.58)
# - Patrón estacional mantenido: Los Q4 siguen siendo los trimestres con mayor producción

# Calidad del pronóstico: Los intervalos de confianza son relativamente estrechos
# (≈ ±40 megalitros para el 80% de confianza), indicando buena precisión predictiva.

# =============================================================================
# f) Prueba de residuales (Diagnóstico del modelo)
# =============================================================================
cat("\nPrueba de Ljung-Box para residuales:\n")
## 
## Prueba de Ljung-Box para residuales:
checkresiduals(model)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(0,1,2)(0,1,1)[4]
## Q* = 3.2579, df = 5, p-value = 0.6603
## 
## Model df: 3.   Total lags used: 8
# Prueba Ljung-Box: p-value = 0.6603
# Conclusión: Los residuales NO PRESENTAN AUTOCORRELACIÓN (p-value > 0.05),
# lo que confirma que el modelo captura adecuadamente la estructura de la serie
# y que los residuales son ruido blanco.

# El modelo SARIMA(0,1,2)(0,1,1)[4] es apropiado para la serie de producción
# de cerveza, capturando adecuadamente tanto la tendencia como la estacionalidad.
# Los pronósticos para 1995-1996 mantienen el patrón estacional histórico y
# presentan una precisión aceptable para la planificación de producción.