# series-de-tiempo-con-python
Series de Tiempo con Python
Volver a la portada del cursoManipulació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
asfreqe interpolar los huecos. - Cambiar de frecuencia con
resampley elegir entresumymean. - Suavizar con
rollingy entender losNaNdel inicio. - Comparar periodos con
shift,diffypct_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))
| Mes | pedidos | mes_anterior | cambio | vs_anio_ant |
|---|---|---|---|---|
| 2025-10 | 8082.0 | 7374.5 | 707.5 | 23.4 |
| 2025-11 | 10866.0 | 8082.0 | 2784.0 | 20.8 |
| 2025-12 | 10424.0 | 10866.0 | −442.0 | 17.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.