Python Central HubSign in

Data Analytics with Python / Phase 3: Data Manipulation with Pandas

Resampling and Frequency Conversion

Convert time series between frequencies with resample — downsample with aggregation and OHLC, upsample with fill, and see how resample differs from groupby.

What resampling means

Resampling converts a time series from one frequency to another:

  • Downsampling — high frequency → low frequency (minute data → daily totals). This always needs an aggregation, because many points collapse into one bucket.
  • Upsampling — low frequency → high frequency (weekly data → daily rows). This creates new rows, which start out empty unless you fill them.

.resample() has a similar API to .groupby(): call resample() to define the buckets, then call an aggregation like .sum() or .mean().

Downsampling: many points into one bucket

Python
import pandas as pd
 
idx = pd.date_range("2024-01-01", periods=12, freq="min")
ts = pd.Series(range(12), index=idx)
 
print(ts.resample("5min").sum())

Two choices control how buckets are formed:

  • closed — which edge of each interval is inclusive ("left" or "right").
  • label — whether the result is labeled with the left or right edge.
Python
print(ts.resample("5min", closed="right").sum())
print(ts.resample("5min", closed="right", label="right").sum())

OHLC: a finance-flavored aggregation

For price data, a common summary per bucket is open, high, low, close — computed in one call:

Python
print(ts.resample("5min").ohlc())

Upsampling: creating new rows

Going from weekly to daily creates rows that don't exist yet — they start as NaN unless you tell pandas how to fill them:

Python
weekly = pd.DataFrame(
    {"a": [1, 2]},
    index=pd.date_range("2024-01-03", periods=2, freq="W-WED"),
)
 
print(weekly.resample("D").asfreq())  # new rows are NaN
print(weekly.resample("D").ffill())   # new rows carry the last known value forward

resample vs groupby

Both split data into buckets and apply a function — the difference is what defines a bucket:

  • groupby("column") groups by the values in a column.
  • resample("2D") groups by fixed time intervals, regardless of how many rows fall into each one.
Python
sales = pd.DataFrame(
    {"amount": [10, 20, 30, 40, 50]},
    index=pd.date_range("2024-01-01", periods=5, freq="D"),
)
 
print(sales.resample("2D").sum())

Common pitfalls

  • Downsampling needs an aggregation (.sum(), .mean(), .ohlc(), ...); calling .resample("5min") alone just returns a lazy resampler object, not data.
  • The default for closed/label is "left" for most frequencies but "right" for a handful ("ME", "YE", "QE", "W") — always check the output on real data.
  • Upsampling with .asfreq() introduces NaN; you must explicitly choose .ffill() or another fill strategy if you don't want gaps.

Visualize it

diagram Downsampling vs upsampling mermaid
Downsampling aggregates many high-frequency points into fewer buckets; upsampling creates new, empty rows that need an explicit fill strategy.
sketch High-frequency points collapsing into buckets p5.js
Twelve minute-level points (amber) are grouped by resample into three 5-minute buckets, each collapsed to one summary bar (blue).

🧪 Try It Yourself

Exercise 1 – Downsample Minute Data to 5-Minute Sums

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 2 – Upsample and Forward-Fill

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 3 – Compute OHLC in One Call

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Check your understanding

quizCheck yourself
  1. Which statement describes downsampling?

    Show answer

    A — Converting high-frequency data to a lower frequency, which needs an aggregation — Downsampling collapses many points into one bucket, such as minute data into daily totals. Upsampling creates new rows.

  2. For ts = pd.Series(range(12)) with a minute index, what are the three values of ts.resample("5min").sum()?

    Show answer

    A — 10, 35, 21 — The buckets hold 0 to 4 (sum 10), 5 to 9 (sum 35) and 10 to 11 (sum 21).

  3. What is the difference between weekly.resample("D").asfreq() and weekly.resample("D").ffill()?

    Show answer

    A — asfreq leaves the new rows as NaN while ffill carries the last value forward — Upsampling creates rows that start empty. You must choose a fill such as ffill if you do not want gaps.

  4. For daily sales of 10, 20, 30, 40 and 50, what does sales.resample("2D").sum() return?

    Show answer

    A — 30, 70, 50 — The two-day buckets are 10 + 20, 30 + 40 and the leftover 50.

Next

Resampling collapses data into buckets. Rolling and Moving Window Functions instead slides a window across the data without collapsing rows — great for smoothing noisy series.

Was this page helpful?

Let us know how we did