Ventana móvil en Pandas: Rolling, Expanding y EWM
Updated on
Las medias móviles y las señales suavizadas son fundamentales en el análisis de series temporales, pero muchos equipos tienen problemas con la alineación de ventanas, los valores faltantes y los bucles lentos en Python.
- Problema: Calcular estadísticas móviles “a mano” es propenso a errores y suele quedar desalineado con las marcas de tiempo.
- Agitación: Los bucles y los desplazamientos ad hoc generan errores de desfase (off‑by‑one), huecos en los primeros periodos y notebooks lentos.
- Solución: Usa
rolling,expandingyewmcon las definiciones de ventana adecuadas (min_periods, ventanas basadas en tiempo,center,adjust) para obtener resultados correctos, rápidos y vectorizados.
Want an AI agent that understands your pandas notebooks and rolling-window features?
RunCell is a JupyterLab AI agent that can read your code, analyze DataFrames, understand notebook context, debug errors, and even generate & execute code for you. It works directly inside JupyterLab—no switching windows or copy-pasting.
👉 Try RunCell: runcell.dev (opens in a new tab)
Referencia rápida
| Tipo de ventana | Mejor uso | Parámetros clave |
|---|---|---|
rolling | Medias móviles, volatilidad, funciones personalizadas de ventana | window=3 (o "7D"), min_periods, center, win_type, on |
expanding | Estadísticas acumuladas desde el inicio | min_periods |
ewm | Suavizado con decaimiento exponencial o métricas ponderadas | span, alpha, halflife, adjust, times |
Datos de ejemplo
import pandas as pd
dates = pd.date_range("2024-01-01", periods=8, freq="D")
sales = pd.DataFrame({"date": dates, "revenue": [10, 12, 9, 14, 15, 13, 11, 16]})
sales = sales.set_index("date")Ventanas móviles (fijas y basadas en tiempo)
Ventanas de tamaño fijo
sales["rev_ma3"] = (
sales["revenue"]
.rolling(window=3, min_periods=2)
.mean()
)min_periodscontrola cuándo empiezan a aparecer resultados; las filas tempranas permanecen comoNaNhasta que se cumple el mínimo de observaciones.center=Truealinea la estadística en el centro de la ventana (muy útil para gráficos).
Ventanas basadas en tiempo sobre un índice datetime o columna on=
sales_reset = sales.reset_index()
sales_reset["rev_7d_mean"] = (
sales_reset.rolling("7D", on="date")["revenue"].mean()
)- Usa cadenas de duración (
"7D","48H") para muestreo irregular; pandas selecciona las filas dentro del horizonte de retrospectiva en vez de un conteo fijo. - Para controlar la inclusión de bordes, ajusta
closed="left"o"right"según lo necesites.
Funciones de ventana personalizadas
sales["rev_range"] = (
sales["revenue"].rolling(4).apply(lambda x: x.max() - x.min(), raw=True)
)Configura raw=True para trabajar con arrays de NumPy dentro de apply y ganar velocidad.
Ventanas expansivas (acumulativas)
sales["rev_cum_mean"] = sales["revenue"].expanding(min_periods=2).mean()- Usa expanding cuando cada observación deba ver todo lo ocurrido hasta ese punto (media móvil acumulada, ratios acumulados).
- Combínalo con
shift()para comparar el valor más reciente contra el promedio histórico.
Ventanas con ponderación exponencial
sales["rev_ewm_span4"] = sales["revenue"].ewm(span=4, adjust=False).mean()adjust=Falseutiliza una fórmula recursiva que imita el suavizado típico en paneles analíticos.halflifeofrece un decaimiento intuitivo:ewm(halflife=3)reduce a la mitad el peso cada 3 periodos.- Para marcas de tiempo irregulares, pasa
times="date"(o establece el índice) para ponderar por los deltas de tiempo reales en lugar de por el número de filas.
Cómo elegir la ventana adecuada (chuleta)
| Objetivo | Método recomendado | Notas |
|---|---|---|
| Suavizar ruido a corto plazo | rolling con window pequeño y center=True | Funciona sobre columnas numéricas; mantén min_periods ≥ 1 para ver datos desde el inicio |
| Totales o promedios acumulados desde el inicio | expanding | Sin ventana fija; ideal para KPIs que se acumulan |
| Hacer que las observaciones antiguas pesen menos | ewm(span=...) | Mejor que ventanas rolling grandes para señales tipo momentum |
| Tiempos irregulares | rolling("7D", on="date") o ewm(..., times="date") basados en tiempo | Evita sesgos por días con muestreo más denso |
| Generación de features | rolling().agg(["mean","std","min","max"]) | La multi‑agregación genera rápidamente conjuntos ordenados de features |
Consejos de rendimiento y corrección
- Mantén las columnas de fechas como
datetime64[ns]y define un índice cuando trabajes intensamente con ventanas basadas en tiempo. - Prioriza las agregaciones integradas (
mean,std,sum,count) sobreapplyen Python para ganar velocidad. - Evita el sesgo con información futura: aplica
shift()antes derollingsi estás construyendo features para aprendizaje supervisado. - Combina con
resamplepara normalizar la frecuencia antes de usar ventanas móviles si los datos de origen son irregulares.
rolling, expanding y las ventanas exponenciales cubren la mayoría de las necesidades de suavizado e ingeniería de features sin usar bucles. Combínalos con pandas-to-datetime y pandas-resample para obtener ejes de tiempo limpios, y así conseguir métricas rápidas y fiables listas para gráficos o modelos.