13 · Features rolling y de calendario
Las estadísticas de ventana móvil resumen el comportamiento reciente y los campos de calendario exponen la estacionalidad directamente — dos familias de features que potencian una tabla con lags (si evitas la fuga).
rolling(w).mean()/std()/min()/max() comprimen la ventana reciente en señales de tendencia y volatilidad, mientras los campos del DatetimeIndex (dayofweek, month, is_weekend) le dan al modelo la estacionalidad gratis — pero las features rolling deben desplazarse para usar solo data PASADA.
Sin esto:
Solo los lags crudos pierden la tendencia suavizada y la volatilidad; sin features de calendario el modelo debe redescubrir los patrones semanales/mensuales desde cero. Y una ventana rolling sin desplazar filtra el presente a tus features e infla los puntajes offline.
Las features de retardo le dan al modelo valores recientes crudos. Dos familias más hacen esas features mucho más ricas.
Las estadísticas de ventana móvil (rolling) resumen las últimas w observaciones en un solo número: rolling(w).mean() es un nivel local suavizado (tendencia reciente), rolling(w).std() es la volatilidad reciente, y .min()/.max() capturan el rango reciente. En lugar de alimentar 14 lags diarios ruidosos, puedes alimentar una media móvil de 7 días (señal) más una std móvil de 7 días (régimen/volatilidad) — features más densas y menos ruidosas.
Las features de calendario salen directo del DatetimeIndex: .dayofweek (0=Lun … 6=Dom), .month, .quarter, .day, y banderas derivadas como is_weekend. Estas le entregan la estacionalidad al modelo explícitamente — un árbol puede dividir "si dayofweek ≥ 5 entonces comportamiento de fin de semana" sin tener que inferir el ciclo de 7 días desde los lags.
Hay una trampa que arruina todo: la fuga (leakage). Un rolling(7).mean() simple en la fila t incluye y[t] mismo — el valor exacto que intentas predecir. Úsalo como feature y tu puntaje offline luce mágico y tu puntaje en vivo colapsa. La solución es desplazar la feature rolling en 1 (o calcularla sobre lags ya desplazados) para que las estadísticas rolling de cada fila usen solo data estrictamente antes de t. Las features de calendario son seguras — la fecha de un punto futuro se conoce de antemano — pero cualquier estadística calculada a partir del target debe mirar estrictamente al pasado.
Python (in browser)
Estadísticas rolling sobre valores con shift(1) más campos de calendario enriquecen la tabla con lags; el chequeo de fuga prueba por qué importa el desplazamiento.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Agregas una feature df['roll7'] = df['y'].rolling(7).mean() y tu error de CV cae dramáticamente, pero el modelo en vivo falla. ¿Qué salió mal?
- rolling(w).mean/std/min/max comprimen la ventana reciente en señales de tendencia, volatilidad y rango.
- Los campos de calendario (dayofweek, month, is_weekend) del DatetimeIndex le dan la estacionalidad al modelo explícitamente y siempre son seguros ante la fuga.
- Desplaza las features rolling en 1 para que cada fila use solo data PASADA — una ventana sin desplazar incluye el target y filtra.
Las medias/stds rolling y los dummies de calendario son la receta de features estándar para pronóstico de demanda retail, carga energética y tráfico con gradient boosting.
Si lo quitas: Quita las features rolling/calendario y el modelo pierde tendencia suavizada, contexto de volatilidad y estacionalidad explícita; fíltralas y tus métricas offline se vuelven una mentira reconfortante.