We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Rolling Metrics

Raw metrics can be terribly noisy. Mornings are busier than evenings. Holidays create big dips. A sale creates an artificial spike.

Rolling averages smooth out all that noise by averaging the numbers over a moving time window, so you can see the actual trend. The window can be anything: days, weeks, months, etc.

It's not just the value for a single day. It's the average of the values in the window up to that day. So a 3-day rolling average for January 3rd is the average of January 1st, 2nd, and 3rd.

The rolling() method computes a function over a sliding window of N observations. To make each observation one calendar day, include missing dates first:

events["date"] = events["timestamp"].dt.floor("D")
daily_users = events.groupby("date")["user_id"].nunique().asfreq("D", fill_value=0)

# 7-day rolling average
rolling_7d = daily_users.rolling(7).mean()

Which prints something like:

7-day rolling average:
date
2024-01-01          NaN
2024-01-02          NaN
2024-01-03          NaN
2024-01-04          NaN
2024-01-05          NaN
2024-01-06          NaN
2024-01-07    13.000000
2024-01-08    14.142857
2024-01-09    14.857143
...
Name: user_id, dtype: float64

The first 6 values are NaN because there aren't enough prior days to fill the 7-day window! The min_periods parameter can relax that restriction and start calculating the average as soon as there's at least 1 day of data:

rolling_7d = daily_users.rolling(7, min_periods=1).mean()
7-day rolling average:
date
2024-01-01    10.000000
2024-01-02    11.000000
2024-01-03    11.000000
2024-01-04    11.750000
2024-01-05    12.400000
2024-01-06    12.500000
2024-01-07    13.000000
2024-01-08    14.142857
2024-01-09    14.857143
...
Name: user_id, dtype: float64

I default to 7-day rolling averages for daily metrics. It naturally cancels out day-of-week effects. A 28-day window is better for monthly patterns but reacts more slowly to real changes.

Assignment

SnackStack's dashboards are jittery: raw device temperatures spike and dip too much to read the real trend.

Complete the calculate_rolling_avg function. It accepts an events DataFrame with timestamp and value columns and a window size, and returns a DataFrame sorted by timestamp with a smoothed rolling_avg column.