El análisis de series temporales es uno de los puntos fuertes de R. El paquete forecast, creado por Rob Hyndman, lleva más de una década siendo el estándar para pronósticos estadísticos. Su sucesor, fable, sigue la filosofía del tidyverse y permite trabajar con múltiples series a la vez de forma limpia. Junto a prophet, el paquete de Meta para series con estacionalidad compleja, R cubre prácticamente cualquier necesidad de análisis temporal en 2026.
Conceptos básicos: objetos ts y tsibble
En R tradicional, una serie temporal se representa con la clase ts. En el ecosistema moderno de fable se usa tsibble, que es un tibble con índice temporal:
# Serie temporal clásica con ts ventas_ts <- ts( data = c(120, 135, 148, 162, 158, 175, 190, 185, 201, 215, 222, 235), start = c(2023, 1), # año 2023, mes 1 frequency = 12 # mensual ) # Visualizar plot(ventas_ts, main = "Ventas mensuales", ylab = "Unidades") # Descomposición STL (tendencia + estacionalidad + residuo) stl_resultado <- stl(ventas_ts, s.window = "periodic") plot(stl_resultado)
forecast: pronósticos con ARIMA y ETS
library(forecast) # auto.arima: selecciona automáticamente el mejor modelo ARIMA mod_arima <- auto.arima(ventas_ts, seasonal = TRUE, stepwise = FALSE) summary(mod_arima) # Pronóstico para los próximos 12 meses pron_arima <- forecast(mod_arima, h = 12) plot(pron_arima, main = "Pronóstico ARIMA", ylab = "Ventas") # Acceder a los valores del pronóstico pron_arima$mean # valores centrales pron_arima$lower[, 2] # límite inferior IC 95% pron_arima$upper[, 2] # límite superior IC 95% # Modelo ETS (Error, Trend, Seasonality): suavizamiento exponencial mod_ets <- ets(ventas_ts) summary(mod_ets) pron_ets <- forecast(mod_ets, h = 12) # Comparar modelos por AICc c(arima = mod_arima$aicc, ets = mod_ets$aicc)
Validación del modelo
# Accuracy sobre datos de entrenamiento
accuracy(mod_arima)
# Backtesting: validación hacia atrás con ventana deslizante
e <- tsCV(ventas_ts, forecastfunction = function(x, h) {
forecast(auto.arima(x), h = h)
}, h = 3)
# RMSE medio del backtesting
sqrt(mean(e^2, na.rm = TRUE))
# Diagnóstico de residuos
checkresiduals(mod_arima)
fable: series temporales en tidyverse
fable reescribe forecast siguiendo la filosofía del tidyverse. La estructura de datos es tsibble y los modelos se encajan en un pipeline con el pipe nativo:
library(tsibble)
library(fable)
library(feasts) # features y visualización de series
# Crear tsibble
datos_ts <- tsibble(
mes = yearmonth("2022 Jan") + 0:35,
ventas = c(120, 135, 148, 162, 158, 175, 190, 185, 201, 215, 222, 235,
242, 258, 271, 280, 275, 295, 310, 305, 321, 335, 342, 358,
365, 378, 392, 405, 398, 415, 430, 425, 441, 455, 462, 478),
index = mes
)
# Visualización rápida
autoplot(datos_ts, ventas)
# Ajustar varios modelos a la vez
modelos <- datos_ts |>
model(
arima = ARIMA(ventas),
ets = ETS(ventas),
naive = NAIVE(ventas ~ drift())
)
# Ver resumen de modelos
glance(modelos)
# Pronóstico de los tres modelos
pronosticos <- modelos |>
forecast(h = "6 months")
# Visualizar todos juntos
autoplot(pronosticos, datos_ts, level = 95)
Series múltiples con fable
Una ventaja clara de fable sobre forecast es el manejo de múltiples series:
# tsibble con múltiples series
ventas_multi <- tsibble(
mes = rep(yearmonth("2023 Jan") + 0:11, 3),
producto = rep(c("A", "B", "C"), each = 12),
ventas = c(
c(100, 110, 105, 120, 115, 130, 125, 140, 135, 150, 145, 160),
c(200, 190, 210, 205, 220, 215, 230, 225, 240, 235, 250, 245),
c(50, 55, 60, 58, 65, 70, 68, 75, 72, 80, 78, 85)
),
key = producto,
index = mes
)
# Un modelo por serie
modelos_multi <- ventas_multi |>
model(arima = ARIMA(ventas))
# Pronósticos de las tres series a la vez
pronosticos_multi <- modelos_multi |>
forecast(h = 6)
autoplot(pronosticos_multi, ventas_multi)
prophet: series con estacionalidad compleja
library(prophet)
# prophet espera columnas ds (fecha) y y (valor)
df_prophet <- data.frame(
ds = seq(as.Date("2020-01-01"), by = "month", length.out = 48),
y = c(100, 110, 105, 120, 115, 130, 125, 140, 135, 150, 145, 160,
165, 175, 170, 185, 180, 195, 190, 205, 200, 215, 210, 225,
230, 240, 235, 250, 245, 260, 255, 270, 265, 280, 275, 290,
295, 305, 300, 315, 310, 325, 320, 335, 330, 345, 340, 355)
)
mod_prophet <- prophet(df_prophet,
yearly.seasonality = TRUE,
weekly.seasonality = FALSE,
daily.seasonality = FALSE)
# Crear dataframe futuro y predecir
futuro <- make_future_dataframe(mod_prophet, periods = 12, freq = "month")
pred <- predict(mod_prophet, futuro)
# Visualizar
plot(mod_prophet, pred)
prophet_plot_components(mod_prophet, pred)
Para análisis más avanzados que combinen series temporales con modelos de machine learning, el artículo sobre caret y tidymodels muestra cómo integrar ambos enfoques. Si necesitas procesar grandes volúmenes de datos temporales antes del modelado, DuckDB puede leer y agregar millones de filas directamente desde R.
Imagen: Pexels / Arturo Añez.
