Time Series
Time-indexed data needs calendar-aware grouping, rolling statistics, and explicit timezone rules - pandas DatetimeIndex provides the machinery.
Search across all documentation pages
Time-indexed data needs calendar-aware grouping, rolling statistics, and explicit timezone rules - pandas DatetimeIndex provides the machinery.
Quick-reference recipe card - copy-paste ready.
import pandas as pd
ts = df.set_index("ordered_at").sort_index()
daily = ts["revenue"].resample("D").sum()
roll = daily.rolling(7, min_periods=3).mean()
local = ts.index.tz_convert("America/New_York")When to reach for this:
import pandas as pd
idx = pd.date_range("2025-01-01", periods=48, freq="h", tz="UTC")
events = pd.DataFrame(
{"revenue": range(48), "region": ["East"] * 24 + ["West"] * 24},
index=idx,
)
events.index.name = "ts"
# Daily totals per region (wide)
daily = (
events.groupby([pd.Grouper(freq="D"), "region"])["revenue"]
.sum()
.unstack(fill_value=0)
)
# 7-day rolling mean on East column
daily["East_roll7"] = daily["East"].rolling(7, min_periods=3).mean()
# Business-day reindex with forward fill for reporting gaps
biz = daily.asfreq("B").ffill()
# Display in US Eastern
eastern = events.index.tz_convert("America/New_York")
print(daily.head())
print("first Eastern hour:", eastern[0])What this demonstrates:
Grouper(freq="D") for calendar daily bucketsmin_periods to avoid tiny windowsasfreq + ffill for business-day alignmentDatetimeIndex stores int64 nanoseconds plus timezone metadata.resample groups into regular periods (rule strings like D, ME, h).rolling slides a fixed window; expanding grows from the start.| Rule | Meaning |
|---|---|
h | Hourly |
D | Calendar day |
B | Business day |
ME | Month end |
W-MON | Weekly Monday |
import pandas as pd
# Parse mixed formats, force UTC
pd.to_datetime(series, format="mixed", utc=True)
# Shift for lag features
df["revenue_lag1"] = df["revenue"].shift(1)resample and rolling assume sorted time. Fix: df.sort_index() first.tz_convert for display.MS vs ME changes KPI boundaries. Fix: document reporting calendar with stakeholders.min_periods=window yields many NA. Fix: lower min_periods knowingly or impute gaps.DatetimeIndex end-to-end.| Alternative | Use When | Don't Use When |
|---|---|---|
Polars group_by_dynamic | Large lazy time buckets | Small pandas-only notebooks |
| statsmodels | ARIMA/seasonal decomposition | Simple resample KPIs |
DuckDB date_trunc | SQL-native warehouse aggregates | Single-machine Series ops |
np.convolve | Fixed FIR smoothing on ndarray | Irregular timestamps |
resample works on DatetimeIndex directly.Grouper attaches to column keys in groupby.ts.resample("D").sum().asfreq("D", fill_value=0)weekly = ts.resample("W").sum()
wow = weekly.pct_change()ts.rolling("7D").mean()merge_asof for as-of joins.closed="left" includes left bin edge.label sets which timestamp names the bucket.ts.index.duplicated().any()to_excel.merge_asofStack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 16, 2026