Rolling Windows
Compute rolling means, sums, and standard deviations over a fixed number of rows with rolling(n).mean() and related methods.
Rolling Windows is a free Pandas & NumPy Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Pandas & NumPy Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Are Rolling Windows?
A rolling window (also called a sliding window or moving window) computes a statistic over a fixed-size window of consecutive rows as it slides forward one row at a time. For example, a 7-day rolling mean replaces each day's value with the average of that day and the 6 preceding days. Rolling windows are the foundation of moving averages in finance, smoothing noisy sensor data, and computing trailing metrics in business dashboards.
import pandas as pd
import numpy as np
# Simple example: 3-day rolling mean
data = pd.Series([10, 12, 15, 11, 9, 13, 16, 14, 12, 18],
index=pd.date_range('2024-01-01', periods=10))
rolling_mean = data.rolling(window=3).mean()
print('Original:')
print(data.values)
print('\n3-day rolling mean:')
print(rolling_mean.values.round(2))The rolling() Method and window Parameter
Series.rolling(window=n) returns a Rolling object. The window parameter is the size of the sliding window in number of rows (for integer windows) or a time offset like '7D' (for time-indexed Series). After creating the rolling object, chain any aggregation method: .mean(), .sum(), .std(), .min(), .max(), or even .apply(func). The first window-1 rows will always be NaN because there are not enough preceding rows to fill the window.
import pandas as pd
import numpy as np
prices = pd.Series(
[100, 102, 98, 105, 110, 108, 115, 112, 120, 118],
index=pd.date_range('2024-01-01', periods=10),
name='price'
)
df = pd.DataFrame({'price': prices})
df['MA3'] = df['price'].rolling(3).mean()
df['MA7'] = df['price'].rolling(7).mean()
df['std3'] = df['price'].rolling(3).std()
print(df.round(2))min_periods Parameter
By default, rolling(n) requires exactly n non-NaN values in the window before computing a result. The min_periods parameter reduces this requirement — for example, rolling(7, min_periods=3) computes the mean as soon as at least 3 values are available, producing non-NaN values earlier in the Series. This is useful when you want moving averages at the start of a time series rather than NaN for the first n-1 rows.
import pandas as pd
import numpy as np
prices = pd.Series([100, 102, 98, 105, 110, 108, 115],
index=pd.date_range('2024-01-01', periods=7))
# Default: first 6 rows are NaN
ma7_default = prices.rolling(7).mean()
# min_periods=3: compute mean once 3 values available
ma7_minperiods = prices.rolling(7, min_periods=3).mean()
df = pd.DataFrame({
'price': prices,
'MA7_default': ma7_default,
'MA7_min3': ma7_minperiods
})
print(df.round(2))Rolling Sum for Running Totals
rolling(n).sum() computes the total of the last n rows at each position. A 30-day rolling sum of daily sales gives the trailing monthly revenue for each day — more informative than a static monthly total because it updates every day. Rolling sums are commonly used in retail analytics (last-30-day sales), web analytics (last-7-day active users), and finance (trailing n-period volume).
import pandas as pd
import numpy as np
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=60)
daily_sales = pd.Series(np.random.randint(100, 500, 60), index=dates, name='daily_sales')
df = pd.DataFrame({'daily_sales': daily_sales})
df['trailing_7d'] = df['daily_sales'].rolling(7).sum()
df['trailing_30d'] = df['daily_sales'].rolling(30).sum()
print(df.tail(10).round(0))Rolling Standard Deviation for Volatility
In finance, volatility is measured as the rolling standard deviation of daily returns. A high rolling std means prices are fluctuating wildly; a low rolling std indicates stable prices. This metric drives risk calculations in options pricing and portfolio management. The formula is: compute daily log returns with np.log(price/price.shift(1)), then apply rolling(window).std().
import pandas as pd
import numpy as np
np.random.seed(0)
prices = pd.Series(
100 * np.exp(np.cumsum(np.random.normal(0.001, 0.02, 120))),
index=pd.date_range('2024-01-01', periods=120)
)
# Daily log returns
log_returns = np.log(prices / prices.shift(1))
# 20-day rolling volatility (annualised)
volatility = log_returns.rolling(20).std() * np.sqrt(252)
print('Last 5 rows of daily volatility:')
print(volatility.tail(5).round(4))Time-Based Rolling Windows
Instead of a fixed number of rows, you can specify a time offset as the window: rolling('7D') means 'the last 7 calendar days of data'. This automatically handles uneven time series (missing weekends, holidays) correctly — a row-count window would include a different amount of calendar time depending on gaps, but a time-offset window always spans exactly 7 days of data. The Series must have a DatetimeIndex for time-based windows.
import pandas as pd
import numpy as np
# Business-day index (no weekends)
biz_dates = pd.bdate_range('2024-01-01', periods=15)
sales = pd.Series(np.random.randint(100, 300, 15), index=biz_dates)
# 7-calendar-day window (variable row count near weekends)
df = pd.DataFrame({'sales': sales})
df['rolling_7d'] = sales.rolling('7D').mean()
print(df.round(1))Rolling Apply for Custom Functions
rolling(n).apply(func) passes each window as a NumPy array to your custom function. This enables any rolling computation that is not covered by the built-in aggregations — for example, rolling median absolute deviation, rolling skewness, or rolling first-quartile. The function must accept a 1-D array and return a scalar. Note: apply is slower than built-in methods because it cannot be vectorised.
import pandas as pd
import numpy as np
prices = pd.Series(
[100, 102, 98, 105, 110, 95, 115, 112, 120, 108],
index=pd.date_range('2024-01-01', periods=10)
)
# Rolling range (max - min) over a 5-day window
def rolling_range(arr):
return arr.max() - arr.min()
df = pd.DataFrame({'price': prices})
df['5d_range'] = prices.rolling(5).apply(rolling_range, raw=True)
print(df.round(2))Rolling on DataFrame Columns
You can apply rolling().mean() directly to a DataFrame to compute rolling statistics for all numeric columns simultaneously. Each column gets its own rolling window computed independently. This is useful for computing moving averages of multiple stock prices or multiple product sales lines in a single operation without looping over columns.
import pandas as pd
import numpy as np
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=10)
df = pd.DataFrame({
'AAPL': 100 + np.cumsum(np.random.randn(10)),
'MSFT': 200 + np.cumsum(np.random.randn(10)),
'GOOG': 150 + np.cumsum(np.random.randn(10))
}, index=dates)
# 3-day moving average of all three stocks
ma3 = df.rolling(3).mean()
print('3-day MA for all stocks:')
print(ma3.round(2))Combining Rolling Mean with the Original
A common visualisation pattern is to plot both the raw time series and its rolling mean on the same axes. The rolling mean reveals the trend by smoothing out day-to-day noise, while the raw series shows the volatility. The gap between them indicates how much noise is present. Adding a rolling mean to a DataFrame is as simple as assigning the result to a new column.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=60)
sales = pd.Series(
200 + np.cumsum(np.random.randn(60) * 10),
index=dates, name='Daily Sales'
)
df = pd.DataFrame({'sales': sales})
df['MA7'] = df['sales'].rolling(7).mean()
df['MA30'] = df['sales'].rolling(30).mean()
df.plot(figsize=(12, 5), title='Sales with 7-day and 30-day Moving Average')
plt.ylabel('Sales')
plt.show()Centered Rolling Windows
By default, rolling uses a trailing window (the current row and n-1 preceding rows). Setting center=True creates a centred window where the current row is in the middle, using equal past and future rows. Centred windows produce smoother results and are appropriate for offline smoothing of historical data where future values are known. They are NOT appropriate for live forecasting because they require future data.
import pandas as pd
import numpy as np
np.random.seed(0)
data = pd.Series(
np.sin(np.linspace(0, 4*3.14159, 30)) + np.random.normal(0, 0.3, 30)
)
df = pd.DataFrame({'signal': data})
df['trailing_MA5'] = data.rolling(5).mean()
df['centered_MA5'] = data.rolling(5, center=True).mean()
print('Comparison (first 8 rows):')
print(df.head(8).round(3))Rolling Windows for GroupBy Data
You can compute per-group rolling statistics using groupby().rolling(). For example, computing a 7-day rolling revenue per product category — the window resets at the start of each group, so one product's data does not bleed into another's. After the rolling operation, use .reset_index(level=0, drop=True) to remove the extra group level from the index and align the result back with the original DataFrame.
import pandas as pd
import numpy as np
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=10)
df = pd.DataFrame({
'date': list(dates) * 2,
'product': ['A'] * 10 + ['B'] * 10,
'sales': np.random.randint(50, 200, 20)
}).sort_values(['product', 'date'])
# 3-day rolling mean per product
df['rolling_mean'] = (df
.groupby('product')['sales']
.transform(lambda x: x.rolling(3).mean())
)
print(df.to_string(index=False))Quick Check
Test your understanding of rolling windows from this lesson.
Lesson Recap
In this lesson you learned: rolling(n) creates a sliding window of n rows for which you can compute mean, sum, std, min, max, or custom functions, min_periods reduces the minimum number of values needed to compute a result, and center=True creates centred windows for offline smoothing. Next up we explore expanding windows — cumulative statistics that grow from the start of the Series.
Frequently asked questions
Is the “Rolling Windows” lesson free?
Yes — the full text of “Rolling Windows” is free to read here on the web, and the Pandas & NumPy Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Pandas & NumPy Academy course, upgrade to CoddyKit PRO.
What will I learn in “Rolling Windows”?
Compute rolling means, sums, and standard deviations over a fixed number of rows with rolling(n).mean() and related methods. You practise Pandas & NumPy Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Pandas & NumPy Academy?
No prior experience is required. Pandas & NumPy Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Rolling Windows” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Pandas & NumPy Academy lesson?
Yes. Every Pandas & NumPy Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.