Python · Capítulo 10 · Lección de conceptos · 7 min de lectura

Cómo pandas convierte marcas de tiempo en tendencias

Cuando las marcas de tiempo son el índice, pandas puede reagruparlas en cubos de calendario, deslizar una ventana sobre ellas y comparar un periodo con otro anterior. Tres herramientas, tres ideas distintas de lo que es un 'periodo'.

La idea

Una serie temporal es una tabla donde el orden de las filas y la distancia entre ellas importan. pandas lo hace explícito con un DatetimeIndex: pon order_date en el índice y cada fila sabe dónde está en el calendario. Después puedes hacer tres tipos de pregunta, y cada una tiene una idea distinta de lo que es un "periodo".

Resample corta el calendario en cubos fijos (días, semanas, meses) y agrega lo que hay en cada uno. Rolling desliza por la serie una ventana de longitud fija y agrega lo que hay dentro. Desplazar (shift y pct_change) alinea una fila con otra que está a cierta distancia, y las compara. Los cubos no se solapan, las ventanas sí, y las comparaciones conectan dos filas.

Figura 1

resample('MS'): los pedidos caen en cubos mensuales

orders
order_idorder_date
85122025-01-31 20:11
85132025-01-31 21:02
85142025-02-01 07:08
85152025-02-01 07:17
85162025-02-01 08:37
size() por mes (estas cinco filas)
month_startorders
2025-01-012
2025-02-013

Paso 1 de 4 Cinco pedidos alrededor del cambio de mes. Con order_date como índice, pandas sabe dónde está cada uno en el calendario.

  1. Cinco pedidos alrededor del cambio de mes. Con order_date como índice, pandas sabe dónde está cada uno en el calendario.
  2. resample('MS') traza cubos mensuales que empiezan el día 1. Los dos pedidos del 31 de enero pertenecen al cubo de enero, aunque uno se hiciera a las 21:02.
  3. Los tres pedidos del 1 de febrero caen en el cubo de febrero. El corte es a medianoche, no a la última hora laboral del mes.
  4. .size() cuenta lo que hay en cada cubo y da una fila por cubo. Es un groupby donde los grupos son periodos de calendario, y un mes vacío seguiría teniendo su fila, con 0.

Por qué existe

Casi toda pregunta de negocio tiene el tiempo en un eje: pedidos por mes, una media de siete días en el panel, este noviembre frente al noviembre pasado. Todo eso se puede hacer con groupby y una columna .dt.month, pero tropezarás con lo mismo: una etiqueta de mes que mezcla enero de 2024 con enero de 2025, un mes sin pedidos que simplemente desaparece, una semana que abarca dos meses.

Un DatetimeIndex se encarga de eso. resample mantiene el año junto al mes, da una fila a los meses vacíos y te deja pasar de diario a semanal a mensual cambiando una letra.

También hace honestas las preguntas sobre el tiempo. Un informe que dice "los pedidos fueron planos en el primer trimestre" es una afirmación sobre periodos de calendario, y resample hace explícitos los periodos en el código, así que quien lea tu código puede ver exactamente qué días entraron en qué número. Eso importa sobre todo cuando alguien te pide repetirlo el trimestre siguiente.

Cómo funciona por dentro

Resample: cubos de calendario

orders.set_index('order_date').resample('MS').size() hace tres cosas. Reparte las filas en cubos, agrega cada cubo y rellena todos los cubos entre el primero y el último, incluso los que no tienen filas. La letra elige el cubo: D para día, W para semana, MS para mes que empieza el día 1, ME para mes que termina el último día, QS para trimestre, YS para año.

La etiqueta es lo que confunde a la gente. ME etiqueta un mes con su último día (2025-01-31), MS con su primero (2025-01-01). Ambos agrupan los mismos pedidos, pero si luego alineas la serie con otra construida del otro modo, nada coincide y obtienes un muro de NaN. Elige una para todo el análisis.

size() cuenta filas, sum() suma una columna. Para ingresos primero necesitas una columna line_total, y luego resample('MS')['line_total'].sum(). Elegir entre ambos es la pregunta de siempre: ¿estoy contando eventos o sumando un importe?

Rolling: una ventana deslizante

rolling(7) significa "las últimas siete filas", y cuenta filas, no días. Solo son siete días si la serie tiene exactamente una fila por día. Por eso haces primero resample('D'): garantiza una fila por día, con 0 para los días sin pedidos. Entonces una ventana de 7 es una semana.

Figura 2

Pedidos por día, del 1 al 10 de noviembre de 2025, y la media de 7 días

0 6.25 12.5 18.75 25 Pedidos Nov 1: 16Nov 2: 17Nov 3: 18Nov 4: 12Nov 5: 15Nov 6: 24Nov 7: 22Nov 8: 17Nov 9: 25Nov 10: 22 Nov 1Nov 3Nov 5Nov 7Nov 9 media de 7 días el 7 nov el 8 nov

Paso 1 de 4 Un conteo diario salta de un lado a otro: 12 pedidos el 4 de noviembre, 24 el 6 de noviembre. El ruido de día a día esconde la tendencia.

  1. Un conteo diario salta de un lado a otro: 12 pedidos el 4 de noviembre, 24 el 6 de noviembre. El ruido de día a día esconde la tendencia.
  2. rolling(7).mean() promedia cada día con los seis anteriores. El 7 de noviembre la ventana abarca del 1 al 7: (16+17+18+12+15+24+22) / 7 = 17.71.
  3. Desliza un día y la ventana suelta el 1 de nov y toma el 8 de nov. La media pasa a 17.86. Las ventanas se solapan, así que cada día tiene su propio valor y la línea es suave.
  4. Los seis primeros días no tienen una ventana completa, así que son NaN salvo que fijes min_periods. Una ventana móvil mira hacia atrás, así que reacciona un poco después del cambio.

Una media móvil es un suavizador, no un pronóstico. Reacciona después que los datos, y cuanto más ancha la ventana, más tarde. Siete días quitan el patrón de los días de la semana. Treinta días quitan casi todo lo que vale la pena comentar, y eso es un compromiso, no un fallo.

Crecimiento: compara con otra fila

pct_change() calcula (esta - anterior) / anterior. Con filas mensuales es mes contra mes. pct_change(12) mira doce filas atrás: año contra año. shift(12) te da el valor antiguo como columna propia, útil cuando quieres mostrar los dos números junto al porcentaje.

Figura 3

Pedidos por mes: dos formas de comparar noviembre de 2025

0 200 400 600 800 Pedidos Oct 24: 325Nov 24: 629Dec 24: 698Oct 25: 371Nov 25: 715Dec 25: 777 Oct 24Nov 24Dec 24Oct 25Nov 25Dec 25 oct 2025 nov 2024

Paso 1 de 3 Dos otoños de pedidos mensuales. Ambos tienen el salto navideño: noviembre y diciembre quedan muy por encima de octubre.

  1. Dos otoños de pedidos mensuales. Ambos tienen el salto navideño: noviembre y diciembre quedan muy por encima de octubre.
  2. Mes contra mes: nov 2025 (715) frente al mes anterior, oct 2025 (371). Es +92.7%, pero sobre todo mide que empieza la temporada navideña.
  3. Año contra año: nov 2025 (715) frente a nov 2024 (629). Es +13.7%, una comparación de igual a igual que la temporada no puede distorsionar.

La elección importa cuando los datos tienen temporadas. Los pedidos de Harbor & Pine saltan en noviembre y diciembre cada año, así que el mes contra mes siempre se verá enorme en otoño y dirá poco. El año contra año compara lo igual con lo igual. Los doce primeros meses de una serie no tienen con qué compararse, así que su valor año contra año es NaN.

Desfases de fechas y huecos

La aritmética de fechas funciona con marcas de tiempo: order_date + pd.Timedelta(days=30) es un plazo, y returned_on - order_date da una duración cuyo .dt.days puedes promediar. Para los huecos, reindex contra pd.date_range muestra qué días faltan: el registro de anuncios de pago tiene 1,091 filas para 1,096 días. Luego decides qué significa el hueco: fillna(0) si no tener fila significa que no hubo gasto, o interpolate y ffill si es una medición que falta.

Errores comunes

"rolling(7) significa siete días"

Significa siete filas. En una serie con una fila por día son siete días. En pedidos con un hueco el domingo es una ventana de siete filas que se extiende por ocho días, y la media cambia de significado en silencio. Haz resample primero a una frecuencia regular, o dale a rolling una ventana de tiempo como rolling('7D'), que cuenta días.

"Mes contra mes es la tasa de crecimiento"

Es una tasa de crecimiento, y en un negocio estacional es la menos informativa. El +92.7% de octubre a noviembre te dice que existe la temporada navideña. El +13.7% frente al noviembre pasado te dice que el negocio crece. Nombra la comparación en el título del gráfico, para que nadie lea la primera como si fuera la segunda.

"La etiqueta de resample es el mes de donde vienen los datos"

La etiqueta es un nombre para el cubo y depende de la letra que elegiste: MS da el primer día, ME el último. Ambas son los pedidos de enero. El peligro no es la etiqueta, sino mezclar las dos al unir o alinear dos series: fija la misma frecuencia en ambas antes de unirlas.

Ponte a prueba

Una pregunta. Al responderla, la lección queda marcada en el mapa; nunca bloquea un nivel.

Quieres noviembre de 2025 frente al mismo mes un año antes, a partir de una Serie mensual con una fila por mes. ¿Qué comparación es?

Elige qué puede ejecutarse en este sitio. Puedes cambiarlo cuando quieras desde "Configurar cookies", al pie de cada página.