Saltar al contenido

# series-de-tiempo-con-python

Series de Tiempo con Python

Volver a la portada del curso
Notebook

Manipulación de Datos Temporales

Sección 2 · Manejo de Datos de Series de Tiempo

Notebook: manipulación de datos temporales

En el video anterior cargaste los pedidos diarios de PyShop, seleccionaste por fecha y descubriste los 18 días faltantes. En este notebook trabajas con la serie ya limpia: cambias de frecuencia, calculas medias móviles, comparas cada periodo con el anterior y extraes partes de la fecha. Esta guía acompaña al notebook manipulacion-de-datos-temporales y te dice qué buscar en cada sección y qué resultados debes obtener.

Objetivos

  • Completar la frecuencia diaria con asfreq e interpolar los huecos.
  • Cambiar de frecuencia con resample y elegir entre sum y mean.
  • Suavizar con rolling y entender los NaN del inicio.
  • Comparar periodos con shift, diff y pct_change.
  • Extraer día de la semana, mes y año con el índice o con el accesor .dt.

1. Datos y faltantes

La primera celda define generar_pedidos(); el notebook es autocontenido. La serie trae 1443 filas, pero de 2022-01-01 a 2025-12-31 hay 1461 días:

s = generar_pedidos()
d = s.asfreq("D")                 # agrega los días que faltan como NaN
print(len(s), len(d), int(d.isna().sum()))     # 1443 1461 18
di = d.interpolate()
print(di["2022-03-13":"2022-03-15"].tolist())  # [136.0, 162.5, 189.0]

El 2022-03-14 no tiene registro; interpolate() le asigna 162.5, el punto medio entre 136 y 189. De aquí en adelante se usa di, sin huecos.

2. Cambiar de frecuencia con resample

resample agrupa por intervalos de tiempo y aplica una agregación, como un groupby por fechas. Los pedidos son un flujo: el total del mes es la suma de sus días.

semanal = di.resample("W").sum()
mensual = di.resample("MS").sum()
promedio = di.resample("MS").mean()
print(len(semanal), len(mensual))                   # 210 48
print(mensual.iloc[-1], round(promedio.iloc[-1], 1))  # 10424.0 336.3

Diciembre de 2025 suma 10,424 pedidos, un promedio de 336.3 por día. Ambas cifras son correctas; responden preguntas distintas. "MS" etiqueta cada mes con su primer día. Revisa también los extremos de semanal: "W" cierra cada semana en domingo, así que la primera semana (que termina el 2022-01-02) solo tiene 2 días y suma 245, y la última (que termina el 2026-01-04) solo tiene 3 días y suma 1180. Esas semanas incompletas no se comparan con las demás.

3. Medias móviles con rolling

Una media móvil de 7 días promedia cada día con los 6 anteriores y borra el patrón semanal (lunes alto, sábado bajo). Con 30 días queda una curva todavía más suave.

m7 = di.rolling(7).mean()
m30 = di.rolling(30).mean()
print(round(m7.iloc[-1], 1), round(m30.iloc[-1], 1))   # 355.1 334.6
print(int(m7.isna().sum()))                            # 6

Los primeros 6 valores de m7 son NaN: no hay 7 días previos para promediar. El notebook grafica la serie diaria con las dos medias encima; observa cómo la de 30 días marca los picos de noviembre y diciembre sin el ruido diario.

4. Desfases y cambios: shift, diff y pct_change

Sobre la serie mensual, shift(1) trae el valor del mes anterior a la fila actual; diff() resta ambos; pct_change(12) compara contra el mismo mes del año anterior, lo que elimina la estacionalidad de la comparación.

t = mensual.to_frame()
t["mes_anterior"] = t["pedidos"].shift(1)
t["cambio"] = t["pedidos"].diff()
t["vs_anio_ant"] = t["pedidos"].pct_change(12) * 100
print(t.tail(3).round(1))
Mespedidosmes_anteriorcambiovs_anio_ant
2025-108082.07374.5707.523.4
2025-1110866.08082.02784.020.8
2025-1210424.010866.0−442.017.0

Diciembre baja 442 pedidos contra noviembre, pero sube 17.0 % contra diciembre de 2024. El cambio mensual mezcla estacionalidad con crecimiento; el cambio a 12 meses aísla el crecimiento. En la sección de análisis, diff vuelve a aparecer para quitar la tendencia antes de ARIMA.

5. Partes de la fecha

Con un DatetimeIndex, las partes de la fecha están en el índice: di.index.day_name(), di.index.dayofweek (0 es lunes), di.index.month. Si la fecha está en una columna, se usa el accesor .dt: df["fecha"].dt.month. El notebook crea una columna fin_semana con di.index.dayofweek >= 5 y agrupa: entre semana el promedio es 216.8 pedidos y en fin de semana 176.2. Por día, el lunes promedia 241.5 y el sábado 174.6.

6. Zonas horarias (mención)

Las fechas de PyShop no tienen zona horaria. Si los datos vinieran con hora, tz_localize("America/Mexico_City") asigna la zona sin mover la hora y tz_convert("UTC") la traduce a otra. Para datos diarios no se necesita; con registros por hora de varios países, sí.

Qué debes obtener

18 faltantes, 210 semanas y 48 meses, diciembre de 2025 con 10,424 pedidos (336.3 por día), medias móviles finales de 355.1 y 334.6, y +17.0 % de diciembre contra el año anterior. Si tus números difieren, revisa la semilla (semilla=42) y que interpolaste antes de agregar. Como práctica, calcula con pct_change(12) qué mes de 2025 creció más contra 2024.

Recursos