Skip to content

Rolling and Moving Window Functions

Why moving windows matter

Real time series are noisy — daily sales bounce around, stock prices jitter minute to minute. A moving window function recomputes a statistic (mean, std, …) over a small sliding slice of the data, smoothing out that noise so the underlying trend is easier to see.

Pandas gives you three flavors:

  • .rolling(window).rolling(window) — a fixed-size window that slides forward.
  • .expanding().expanding() — a window that starts small and grows to include everything seen so far.
  • .ewm(span=...).ewm(span=...) — an exponentially weighted window that favors recent observations.

Rolling mean and std

Rolling window basics
import pandas as pd
 
s = pd.Series(
    [10, 12, 13, 12, 15, 20, 18, 22, 25, 30],
    index=pd.date_range("2024-01-01", periods=10, freq="D"),
)
 
print(s.rolling(3).mean())  # 3-day moving average
Rolling window basics
import pandas as pd
 
s = pd.Series(
    [10, 12, 13, 12, 15, 20, 18, 22, 25, 30],
    index=pd.date_range("2024-01-01", periods=10, freq="D"),
)
 
print(s.rolling(3).mean())  # 3-day moving average

rolling(3)rolling(3) behaves like groupbygroupby, but instead of grouping by a key, it creates a sliding 3-row window. Notice the first two values are NaNNaN — there aren’t 3 rows yet to average.

min_periods: dealing with a short warm-up

By default, a rolling window needs every slot filled before it produces a value. min_periodsmin_periods relaxes that, useful right at the start of a series:

min_periods relaxes the warm-up requirement
print(s.rolling(3, min_periods=1).mean())  # no leading NaN this time
min_periods relaxes the warm-up requirement
print(s.rolling(3, min_periods=1).mean())  # no leading NaN this time

Expanding windows

An expanding window is like a rolling window whose size keeps growing — it always starts at the beginning of the series and includes everything up to the current row:

Expanding mean
print(s.expanding().mean())  # cumulative average up to each point
Expanding mean
print(s.expanding().mean())  # cumulative average up to each point

Exponentially weighted windows (ewm)

Instead of weighting every value in the window equally, ewmewm gives more weight to recent observations — it “reacts” faster to a change than a simple moving average:

Exponentially weighted mean
print(s.ewm(span=3).mean())
Exponentially weighted mean
print(s.ewm(span=3).mean())

Rolling correlation (two series at once)

Some window functions — like correlation — need two series. Calling .rolling(...).rolling(...) on one series and then .corr(other).corr(other) computes a rolling correlation between them:

Rolling correlation between two return series
bench = pd.Series(
    [1, 1.2, 1.1, 1.3, 1.5, 1.6, 1.4, 1.7, 1.9, 2.0],
    index=s.index,
)
 
rolling_corr = s.pct_change().rolling(4, min_periods=2).corr(bench.pct_change())
print(rolling_corr)
Rolling correlation between two return series
bench = pd.Series(
    [1, 1.2, 1.1, 1.3, 1.5, 1.6, 1.4, 1.7, 1.9, 2.0],
    index=s.index,
)
 
rolling_corr = s.pct_change().rolling(4, min_periods=2).corr(bench.pct_change())
print(rolling_corr)

Common pitfalls

  • Without min_periodsmin_periods, the first window - 1window - 1 rows of a rolling result are always NaNNaN.
  • Rolling window functions automatically skip missing data, but they still require min_periodsmin_periods valid values to produce output.
  • ewmewm doesn’t have a fixed “window size” the way rollingrolling does — spanspan just controls how quickly old observations lose influence.

Visualize it

diagram Three ways to slide a window mermaid
rolling keeps a fixed-size window; expanding grows from the start; ewm weights recent points more heavily instead of using a hard cutoff.
sketch A rolling window smoothing a noisy series p5.js
The amber line is the raw noisy series; the blue line is its 3-point rolling mean, visibly smoother.

🧪 Try It Yourself

Exercise 1 – Compute a Rolling Mean

Exercise 2 – Avoid Leading NaN With min_periods

Exercise 3 – Compute an Expanding Mean

Next

That completes the Pandas phase. Head into Phase 4 — Data Preprocessing and Cleaning, starting with Understanding Data Quality, to apply these skills to real, messier datasets.

If this helped you, consider buying me a coffee ☕

Buy me a coffee

Was this page helpful?

Let us know how we did