Pandas Time Series
Deep dive · part of Python Pandas Basics
Pandas has first-class support for time series: parsing, resampling, rolling windows, time-zone conversion and date offsets. A DatetimeIndex unlocks slicing by date strings and the .dt accessor.
DatetimeIndex enables date slicing (s['2025-02']), resample for aggregation periods, rolling windows for moving averages, and tz_localize/tz_convert for timezone-aware analytics. pd.to_datetime parses heterogeneous date strings in ETL.
Business calendars need CustomBusinessDay or holidays library—not plain calendar days.
Financial and ops dashboards depend on correct bucket boundaries: weekly resample labels, month-end anchors, and fiscal calendars that differ from calendar months all deserve explicit tests before executives trust the charts.
Production code combines this topic with logging, tests, and clear module boundaries so refactors stay safe when requirements grow.
date_range generates regular spans; freq='D', 'h', 'B' (business).
resample('W').mean() downsamples; asfreq upsamples with optional fill.
rolling(7).mean() sliding window; center=True aligns labels.
dt accessor on Series extracts year, weekday, quarter.
tz-aware Series require consistent tz before arithmetic.
shift and diff build lag features for forecasting.
Merge asof joins time series on nearest key—useful for irregular sensor logs. Period versus Timestamp types differ—convert explicitly in legacy code.
Arrow-backed dtypes in pandas 2+ improve memory for large time columns.
Feature stores often precompute rolling means and lag columns with shift(1) to prevent leakage—document each column's time semantics beside the DataFrame schema.
Sort index before rolling and resample; unsorted time series produce misleading window statistics.
Read the parent tutorial on pythondeck.com for runnable snippets, then reproduce them locally in a virtual environment with pinned dependency versions matching your deployment target.
When pairing with teammates, agree on one idiomatic pattern per concern—mixed styles in one repo slow reviews and invite subtle integration bugs during merges.
Mixing tz-naive and tz-aware without localize.
Resampling without label='right' confusion on bucket boundaries.
Parsing dayfirst vs monthfirst dates wrong in to_datetime.
Rolling on unsorted index producing nonsense—sort_index first.
Set datetime index explicitly after parse in pipelines.
Store UTC internally; convert to local only in presentation.
Document freq semantics in notebook headers for stakeholders.
Test resample on edge dates (leap years, DST shifts).
Re-read the examples below with these ideas in mind; change variable names and inputs to match your own project.
The program below demonstrates parse + resample. Read the comments on each line, run the code, then change names or values to see how the output shifts.
# Example: Parse + resample
# Run in the REPL or save as a .py file and execute with python.
import pandas as pd, numpy as np
idx = pd.date_range("2025-01-01", periods=180, freq="D")
s = pd.Series(np.random.randn(180).cumsum(), index=idx)
print(s.resample("W").mean().head())
print(s["2025-02"].head())
This sample walks through rolling window in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.
# Example: Rolling window
# Run in the REPL or save as a .py file and execute with python.
import pandas as pd, numpy as np
idx = pd.date_range("2025-01-01", periods=30, freq="D")
s = pd.Series(np.random.randn(30), index=idx)
print(s.rolling(7).mean())
Here is a hands-on illustration of time-zone aware. Follow the inline comments first; only then execute the snippet and compare the result with what you expected.
# Example: Time-zone aware
# Run in the REPL or save as a .py file and execute with python.
import pandas as pd
idx = pd.date_range("2025-06-01", periods=3, freq="h", tz="UTC")
s = pd.Series([1, 2, 3], index=idx)
print(s)
print(s.tz_convert("Europe/London"))
The program below demonstrates resample weekly. Read the comments on each line, run the code, then change names or values to see how the output shifts.
# DatetimeIndex enables resample for period aggregations
import pandas as pd # pandas
import numpy as np # nums
idx = pd.date_range("2025-01-01", periods=14, freq="D") # daily
s = pd.Series(np.arange(14), index=idx) # series
weekly = s.resample("W").mean() # weekly mean
print(weekly.head()) # first buckets
print(weekly.index.min()) # first period label
print(s.resample("W").sum().iloc[0]) # weekly sum first bucket
This sample walks through rolling mean in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.
# rolling provides moving window statistics
import pandas as pd # pandas
import numpy as np # numpy
idx = pd.date_range("2025-01-01", periods=10, freq="D") # dates
s = pd.Series(np.random.randn(10), index=idx) # noise
roll = s.rolling(3).mean().dropna() # 3-day moving average
print(roll.head()) # first valid windows
print(s["2025-01-02":"2025-01-05"]) # label slicing
print(s.index.dtype) # datetime64 dtype
Related deep dives on Python Pandas Basics: