Series temporales: cuando el orden lo cambia todo
Un sistema de monitorización registra el consumo eléctrico de una fábrica cada hora. Si intentas predecir el consumo de la próxima hora usando solo el promedio histórico general, te equivocarás de forma sistemática: no capturarás que a las 6 de la mañana se encienden los hornos, ni que los viernes la producción baja. El problema no es falta de datos — es que estás ignorando la variable más informativa de todas: cuándo ocurrió cada observación.
Las series temporales son secuencias de observaciones ordenadas en el tiempo. Cada punto de datos no existe de forma aislada: está relacionado con lo que pasó antes y, a veces, anticipa lo que vendrá después. Ese orden causal es la diferencia que lo cambia todo.
Qué convierte unos datos en una serie temporal
En el análisis de datos clásico puedes barajar las filas de tu tabla sin perder información. Las ventas del cliente 1247 no dependen de las del cliente 1246. Cada fila es una observación independiente.
En una serie temporal, barajar destruye la información más valiosa. Formalmente, una serie temporal es:
donde cada está condicionado por , y otros valores pasados. Esa dependencia temporal no es un problema a resolver — es la señal que queremos modelar.
| Tipo de dato | Ejemplo | ¿Importa el orden? | Método de análisis |
|---|---|---|---|
| Corte transversal | Encuesta de satisfacción | No | Regresión, clustering |
| Panel | Ventas por tienda y mes | Sí (parcialmente) | Efectos fijos, ML con features de fecha |
| Serie temporal | Consumo eléctrico horario | Sí, totalmente | Modelos temporales (ARIMA, ETS, ML temporal) |
Cada serie tiene detrás un proceso generador de datos (DGP): el mecanismo real que produce las observaciones. El consumo eléctrico tiene un DGP con ciclos de 24 horas, picos semanales y variaciones estacionales anuales. Nuestro objetivo nunca es capturar el DGP completo —es imposible— sino aproximarlo lo suficiente como para hacer predicciones útiles.
Los cuatro componentes de una serie temporal
Casi cualquier serie temporal puede descomponerse en cuatro piezas. Reconocerlas a simple vista —antes de tocar ningún modelo— es la habilidad más práctica de este capítulo.
El modelo de descomposición aditiva expresa cada observación como la suma de cuatro componentes:
donde es tendencia, estacionalidad, ciclo y el término de error o ruido.
Tendencia (): el rumbo a largo plazo
La tendencia refleja el movimiento sostenido de la media a lo largo del tiempo. Puede ser creciente, decreciente o prácticamente plana. La forma más simple es lineal:
donde es el nivel inicial y la pendiente (positiva = serie al alza, negativa = serie a la baja).
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
np.random.seed(42)
fechas = pd.date_range(start="2020-01-01", periods=60, freq="ME")
t = np.arange(60)
# Tendencia lineal: nivel inicial 100, crecimiento de 1.2 unidades por mes
tendencia = 100 + 1.2 * t
plt.figure(figsize=(10, 4))
plt.plot(fechas, tendencia, color="#1a1a1a", linewidth=2)
plt.title("Tendencia lineal creciente")
plt.xlabel("Fecha")
plt.ylabel("Valor")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Estacionalidad (): el patrón que se repite
La estacionalidad es un patrón periódico de amplitud relativamente constante que se repite a intervalos fijos: cada 7 días, cada 12 meses, cada 24 horas. Es la firma temporal de los hábitos humanos, los ciclos naturales y los calendarios comerciales.
donde es la amplitud del patrón y el período (número de períodos por ciclo).
# Estacionalidad anual: el patrón se repite cada 12 meses
amplitud = 15.0
periodo = 12
estacionalidad = amplitud * np.sin(2 * np.pi * t / periodo)
Ruido (): la variación que no explicas
El ruido —también llamado componente irregular o residual— recoge todo lo que el modelo no captura: el impacto puntual de una campaña de marketing, un fallo técnico inesperado, una noticia que nadie anticipó. En un modelo bien especificado, el ruido debe parecerse al ruido blanco: media cero, varianza constante y sin autocorrelación.
# Ruido blanco: distribución normal con media 0 y desviación estándar 5
sigma = 5.0
ruido = np.random.normal(loc=0, scale=sigma, size=60)
Ciclos (): oscilaciones de duración variable
Los ciclos son fluctuaciones de más largo plazo que no tienen un período fijo. El ejemplo más conocido son los ciclos económicos de expansión y contracción, que pueden durar entre 4 y 12 años. A diferencia de la estacionalidad, no puedes predecir cuándo empezará el siguiente ciclo con solo conocer el período.
# Superposición de dos oscilaciones con períodos irregulares
ciclo_a = 8 * np.sin(2 * np.pi * t / 28) # ciclo lento (~28 meses)
ciclo_b = 4 * np.sin(2 * np.pi * t / 11) # ciclo rápido (~11 meses)
ciclo = ciclo_a + ciclo_b # el resultado no es periódico
En la práctica, el componente cíclico es el más difícil de identificar y modelar. Muchas implementaciones de descomposición lo incluyen en la tendencia o en el residual.
La serie completa: todo junto
Al combinar los cuatro componentes obtienes una serie que parece “real”: tiene una dirección general, un patrón recurrente, variaciones irregulares y pequeñas oscilaciones de largo plazo.
# Serie completa bajo el modelo aditivo
serie = tendencia + estacionalidad + ruido
Activa y desactiva cada componente para ver cómo contribuye a la forma de la serie:
Y_t = T_t + S_t + ε_t La serie completa combinada tiene 60 meses. Usa el slider para cambiar la ventana de la media móvil y observa cómo a medida que la amplias, la línea amarilla se acerca más a la tendencia real ignorando el ruido estacional:
Con ventana = 12 meses, la media móvil elimina exactamente un ciclo de estacionalidad anual y deja visible solo la tendencia. Con ventana = 1, es equivalente a la serie original sin suavizar.
Tres dominios, tres historias distintas
Ver los componentes en abstracto está bien. Verlos en datos con contexto real es lo que fija el aprendizaje. Aquí tienes tres escenarios con patrones muy distintos.
Negocios: ingresos recurrentes de una plataforma SaaS
Una startup SaaS registra sus ingresos mensuales recurrentes (MRR) durante 24 meses. La empresa crece, así que hay tendencia. Los cierres de contrato se concentran en Q4 (antes del cierre fiscal de sus clientes corporativos), así que hay estacionalidad anual.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
np.random.seed(42)
fechas = pd.date_range(start="2024-01-01", periods=24, freq="ME")
t = np.arange(24)
mrr_base = 5000.0
# Crecimiento exponencial del 4% mensual
tendencia_mrr = mrr_base * np.exp(0.04 * t)
# Pico en Q4 (meses 10-11 del año): estacionalidad con fase adelantada
estacional_mrr = 0.12 * tendencia_mrr * np.sin(2 * np.pi * t / 12 + np.pi / 6)
ruido_mrr = np.random.normal(0, 150, 24)
mrr = tendencia_mrr + estacional_mrr + ruido_mrr
serie_mrr = pd.Series(mrr, index=fechas)
plt.figure(figsize=(10, 4))
plt.plot(serie_mrr, color="#1a1a1a", linewidth=2)
plt.title("MRR de plataforma SaaS — 24 meses")
plt.xlabel("Fecha")
plt.ylabel("MRR (€)")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
IoT: temperatura de un servidor de cómputo
Un servidor de entrenamiento de modelos de ML registra su temperatura CPU cada hora durante 48 horas. La temperatura sube durante la jornada laboral (9-18h, cuando los trabajos se lanzan) y baja de noche.
np.random.seed(123)
horas = pd.date_range(start="2024-01-15 00:00", periods=48, freq="h")
t_h = np.arange(48)
temp_base = 35.0
# Ciclo diario: temperatura sube en horas de trabajo, solo valores positivos
temp_ciclo = 12.0 * np.maximum(0, np.sin(2 * np.pi * t_h / 24 - np.pi / 2))
ruido_termico = np.random.normal(0, 1.2, 48)
temperatura = temp_base + temp_ciclo + ruido_termico
serie_temp = pd.Series(temperatura, index=horas)
plt.figure(figsize=(10, 4))
plt.plot(serie_temp, color="#1a1a1a", linewidth=1.8)
plt.axhline(45, color="#ff8b94", linestyle="--", alpha=0.7, label="Umbral de alerta (45°C)")
plt.title("Temperatura CPU — 48 horas")
plt.xlabel("Hora")
plt.ylabel("Temperatura (°C)")
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Finanzas: precio de cierre de un activo
El precio de un activo financiero durante 252 días de trading (aproximadamente un año) sigue un paseo aleatorio: cada precio es el anterior más una perturbación aleatoria.
np.random.seed(42)
dias_trading = pd.date_range(start="2024-01-02", periods=252, freq="B") # días hábiles
# El precio de hoy = precio de ayer + variación aleatoria (paseo aleatorio)
variaciones = np.random.normal(0, 1.2, 252)
precio = 100 + np.cumsum(variaciones)
serie_precio = pd.Series(precio, index=dias_trading)
plt.figure(figsize=(10, 4))
plt.plot(serie_precio, color="#1a1a1a", linewidth=1.5)
plt.title("Precio de cierre — 252 días de trading")
plt.xlabel("Fecha")
plt.ylabel("Precio (€)")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Autoevaluación
Barajas aleatoriamente las filas de tu dataset de series temporales antes de entrenarlo en un modelo. ¿Qué consecuencia tiene esto?
De los cuatro componentes, ¿cuál tiene un período estrictamente fijo y predecible?
Analizas ventas de ropa de abrigo. Observas que en invierno los picos son cada vez más altos a medida que la empresa crece. ¿Qué modelo de descomposición es más apropiado?
En un lag plot donde graficas $y_t$ en el eje Y contra $y_{t-1}$ en el eje X, los puntos forman una nube sin estructura. ¿Qué indica esto?
Reto de código
Resumen
- Una serie temporal es una secuencia donde el orden de las observaciones importa: cada valor depende de los anteriores. Barajar los datos destruye esa estructura.
- Casi cualquier serie puede descomponerse en tendencia (rumbo a largo plazo), estacionalidad (patrón periódico fijo), ciclo (oscilaciones de duración variable) y ruido (variación aleatoria irreducible).
- Los patrones difieren drásticamente según el dominio: los ingresos SaaS tienen tendencia dominante, los sensores IoT tienen estacionalidad diaria, los precios financieros se parecen a paseos aleatorios.
En los subcapítulos siguientes vas a pasar de la teoría al código:
- 1.1 — Construye y destruye: genera cada componente en Python, combínalos y verifica la descomposición automática.
- 1.2 — El arsenal de pandas: domina el
DatetimeIndex,resample,rollingy el manejo de datos faltantes. - 1.3 — Diagnóstico visual: las cinco gráficas que debes hacer antes de ajustar cualquier modelo.
El capítulo 2 presentará el concepto de estacionariedad —la propiedad estadística que determina qué modelos puedes aplicar y cómo— junto con tu primer modelo ARIMA.