Saltar al contenido

lección 3

Martes: limpiar, agregar la serie y fabricar las features

Limpiar y agregar los avisos a una serie por zona, fecha y hora, cazar los huecos, y fabricar los lags, las medias móviles y el calendario.

⏱ 55 min

## Martes, 10:00. El día menos glamuroso y el más importante

Ayer dibujaste el mapa; hoy toca el trabajo que ocupa la mayor parte del tiempo de un científico de datos y que nadie enseña en los cursos: dejar la serie en condiciones de que un modelo la pueda usar. No es glamuroso y no sale en las fotos, pero es donde se gana o se pierde el proyecto. Un modelo entrenado sobre una serie sucia o mal alineada aprende la suciedad, da igual lo bueno que sea el algoritmo. Hoy tienes tres trabajos encadenados: limpiar los avisos, agregarlos a una serie por zona/fecha/hora, y fabricar las pistas temporales. Al terminar tendrás la tabla con la que de verdad vas a modelar.

Conviene tener claro el orden desde el principio, porque hacerlo al revés estropea el resultado. Primero se limpia, después se agrega, y solo al final se fabrican las features. Si construyeras los lags antes de ordenar y limpiar la serie, estarías mirando "la hora anterior" de una fila que en realidad no es la anterior, y el lag quedaría mal alineado. Y si agregaras sin haber reconstruido el índice horario, un hueco (una hora sin fila) haría que el lag de una fila saltara por encima del hueco y cogiera la demanda de hace tres horas creyendo que es la de hace una. El orden no es una manía: cambia los números.

## Lo primero y lo más traicionero: las tres formas de fecha

La marca de tiempo es la columna de la que depende toda la serie, así que si se parsea mal, todo lo demás se derrumba. Viene en tres formatos mezclados. Los dos primeros los resuelve pandas con una sola llamada: su función de parseo de fechas acepta un modo que detecta el formato de cada fila por su cuenta, y con la opción de "día primero" entiende tanto el ISO ("2023-07-26 22:26") como el español de día primero ("27/03/2023 22:17"). El problema es el tercero: "19 ago 2023 08:09", con el mes abreviado en español. Pandas no sabe que "ago" es agosto —espera los meses en inglés—, así que esa fila revienta el parseo entero si la metes en el mismo saco.

La solución honesta es tratar ese formato aparte: detectar las filas que llevan un mes en letra, sustituir la abreviatura española por el número de mes ("ago" por "08", "mar" por "03", y así) y solo entonces parsear. No hay un atajo mágico que lo haga todo de una vez, y por eso este es un buen sitio para que escribas tú la función: se te da la firma y el diccionario de meses, y tú implementas la conversión. El andamiaje es más fino que en tus casos anteriores a propósito: ya tienes tres encargos encima, y a estas alturas se espera que escribas una función de limpieza a partir de su diseño, no que rellenes un hueco de una línea.

No intentes parsear las tres formas con una sola llamada en el modo automático de pandas. La fila con el mes en español ("19 ago 2023") hace que la llamada falle con un error que menciona "ago", y es un fallo silencioso de los peores: o revienta todo el parseo, o —según cómo lo montes— convierte en nulo una de cada tres fechas sin avisar, y pierdes un tercio de la serie sin enterarte. El mes en español se convierte a número ANTES de parsear. Es el gran defecto a evitar del día, y por eso lo escribes tú.

Dos de las tres formas las parsea pandas directamente; la del mes en español necesita un paso previo que convierta la abreviatura a número. Meter las tres en la misma llamada rompe el parseo.

## Después: zonas, duplicados y la serie

Con las fechas en condiciones, el resto de la limpieza es más llevadero. La zona se normaliza quitando los espacios de los lados y pasándola a minúsculas, y mapeando cada variante a su zona canónica: "zgz", "zaragoza", "zaragoza centro" van todas a "Zaragoza", y así con las cuatro. Los duplicados se quitan con una deduplicación por aviso_id —y solo por aviso_id, nunca por timestamp, por lo que viste ayer—. Y entonces llega la agregación: se agrupa por zona, fecha y hora, y se cuenta cuántos avisos cae en cada grupo. Ese recuento es n_servicios, el target. La serie empieza a existir.

Pero falta un paso que no había en tus casos anteriores, y es propio de las series: reconstruir el índice horario. Cuando una hora no tiene ningún aviso —una madrugada tranquila, o un rato en que el CAU se cayó—, no hay fila en la serie agregada, simplemente no existe. Y eso NO es lo mismo que n_servicios igual a cero. El problema es que un hueco envenena los lags: si falta la hora de las 4 de la madrugada, el lag de "hace una hora" de las 5 cogería la demanda de las 3, creyendo que es la de las 4. Por eso hay que reconstruir el calendario horario completo por zona —todas las horas de principio a fin, estén o no— y así ver exactamente qué horas faltan antes de calcular ninguna pista.

Cuando faltan horas, la serie salta por encima del hueco y los lags se desalinean. Reconstruir el índice horario completo hace visibles esos huecos antes de calcular ninguna pista. Un hueco no es un cero: puede ser demanda baja real o un fallo del sistema.

## El corazón del caso: los lags, las medias móviles y el calendario

Y ahora, lo que hace posible el forecasting sin ARIMA: convertir la serie en una tabla de pistas. La idea es que, por cada fila (una zona, una hora), se añaden columnas con información que el modelo habría conocido en ese momento. Pero antes de fabricar ninguna, una pregunta que manda sobre todas: ¿con cuánta antelación predices? La central cierra los turnos con dos semanas de margen. Ese es el horizonte: 14 días, 336 horas. Cuando predices el martes 12 a las 10, lo último que conoces es la demanda del martes 29 a las 10. Así que ninguna pista puede mirar a menos de 14 días. Los lags son la demanda de hace 14 días (la misma hora y el mismo día de la semana, dos semanas antes), de hace 21 y de hace 28. Se calculan desplazando la columna de demanda hacia abajo dentro de cada zona: 336 posiciones para 14 días, 504 para 21, 672 para 28. Las medias móviles resumen el nivel reciente que sí conoces: la media de las 24 horas y la de la semana que acaban hace 14 días. Y el calendario sale de la propia marca de tiempo: la hora, el día de la semana, el mes, y si es festivo, que se conocen con meses de antelación.

Aquí está el defecto sutil que tienes que cazar y corregir hoy, y es de higiene, no el gran insight del caso. Una media móvil, tal como se escribe de forma natural, incluye la propia hora en el promedio: la media de las últimas 24 horas calculada en la fila de las 10 incluye la demanda de las 10, que es justo la que querrías predecir, y la de las 23 horas anteriores, que a 14 días vista tampoco conocerías. Eso es una fuga: le estás dando al modelo, como pista, un trocito de la respuesta. La corrección es desplazar la serie el horizonte entero (336 posiciones) antes de promediar, de modo que la media de la fila de las 10 se calcule sobre las 24 horas que acaban hace 14 días. Se corrige en una línea, y no tiene nada que ver con el problema del jueves —ese es de cómo se parte la serie, no de las features—.

Consejo de senior: la regla para no colar fugas en las features de una serie es sencilla de decir y fácil de olvidar: toda pista que uses para predecir la hora H tiene que calcularse SOLO con información que ya tendrías cuando predices, es decir, de H menos el horizonte hacia atrás. Un lag de 14 días cumple eso por construcción. Una media móvil no, a menos que la desplaces el horizonte entero. Cuando construyas cualquier feature nueva, hazte la pregunta: el día que cierro el cuadrante, ¿ya conozco esto? Si la respuesta es no, tienes una fuga.

Al terminar de construir los lags y las medias, las primeras filas de cada zona se quedan con huecos: las cuatro primeras semanas no tienen "hace 28 días". Esas filas con pistas incompletas se descartan, porque el modelo no puede aprender de una pista que no existe. Lo que queda, limpio y con todas sus pistas, es la tabla de modelado: el entregable del martes.

Trabajas con los CSV de CoberturaYa en la carpeta datos/: servicios (los avisos crudos), zonas, meteo y calendario_festivos. Hoy construyes la serie a partir de ellos. Para fabricar las features partes de serie_horaria.csv, la serie ya agregada con los huecos a la vista. Los ejercicios de modelado de los próximos días reconstruyen esta misma tabla con el mismo bloque de código, para partir todos del mismo punto.

volver a la visión del caso y descargar los datasets

Regístrate para guardar tu progreso.