Lesson 14 · Python For Time Series
Master Rolling Mean & Exponential Moving Average in Python for Time Series Analysis
Welcome! In this lesson, we will learn two key ways to analyze trends in data: rolling mean and exponential moving average. These tools help us smooth out…
- CoursePython For Time Series
- Lesson14 of 30
- Video16 min
- FormatJupyter notebook · 20 code cells
What you'll learn
Data
No separate download needed — the notebook creates or downloads everything it uses.
📓 Full notebook
Download .ipynb
Rolling Mean and Exponential Moving Average in Python#
Welcome! In this lesson, we will learn two key ways to analyze trends in data: rolling mean and exponential moving average. These tools help us smooth out noisy data to see underlying patterns.
By the end, you will know how to use them on real-world datasets and apply them to your own projects.
# Let us turn off warnings for a smoother experience.
import warnings
warnings.filterwarnings("ignore")
# Let us import the libraries we need.
import pandas as pd
import matplotlib.pyplot as plt
What is a Rolling Mean?#
A rolling mean, also called a moving average, calculates the average value over a sliding window in your data.
It helps you spot trends by smoothing out short-term ups and downs.
# Data setup: let us load monthly airline passenger data.
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/airline-passengers.csv"
df = pd.read_csv(url)
print("Shape:", df.shape)
df.head()
# Let us plot the passenger numbers over time.
plt.figure(figsize=(10,4))
plt.plot(df['Passengers'])
plt.title("Airline Passengers Over Time")
plt.xlabel("Month")
plt.ylabel("Number of Passengers")
plt.show()
Rolling Mean in Practice#
We can use pandas to calculate a rolling mean using the .rolling() and .mean() methods.
Let us start with a window size of 3 months. This means our mean at each point is the average of that month and the two before.
# Calculate the 3-month rolling mean and add as a new column.
df['RollingMean3'] = df['Passengers'].rolling(window=3).mean()
# Show the result for the first 10 rows
df[['Passengers', 'RollingMean3']].head(10)
# Let us plot the original data and the rolling mean.
plt.figure(figsize=(10,4))
plt.plot(df['Passengers'], label='Original')
plt.plot(df['RollingMean3'], label='3-Month Rolling Mean', color='orange')
plt.title("Passengers and Rolling Mean")
plt.xlabel("Month")
plt.ylabel("Number of Passengers")
plt.legend()
plt.show()
Exponential Moving Average (EMA)#
A rolling mean averages all values in its window equally. But what if we want to give more weight to newer months?
That is what an Exponential Moving Average does. It reacts faster to new changes.
# Calculate the Exponential Moving Average (span=3 months)
df['EMA3'] = df['Passengers'].ewm(span=3, adjust=False).mean()
# Show first 10 values for comparison
df[['Passengers', 'RollingMean3', 'EMA3']].head(10)
# Plot all three: original, rolling mean, E M A.
plt.figure(figsize=(10,4))
plt.plot(df['Passengers'], label='Original')
plt.plot(df['RollingMean3'], label='3-Month Rolling Mean', color='orange')
plt.plot(df['EMA3'], label='EMA (Span=3)', color='green')
plt.title("Rolling Mean vs EMA")
plt.xlabel("Month")
plt.ylabel("Passengers")
plt.legend()
plt.show()
# Try using a bigger window for rolling mean and E M A (12 months).
df['RollingMean12'] = df['Passengers'].rolling(window=12).mean()
df['EMA12'] = df['Passengers'].ewm(span=12, adjust=False).mean()
plt.figure(figsize=(10,4))
plt.plot(df['Passengers'], label='Original', alpha=0.5)
plt.plot(df['RollingMean12'], label='12-Month Rolling Mean', color='red')
plt.plot(df['EMA12'], label='EMA (Span=12)', color='purple')
plt.title("Yearly Rolling Mean and EMA")
plt.xlabel("Month")
plt.ylabel("Passengers")
plt.legend()
plt.show()
# Using input to pick a window size for rolling mean.
window = int(input("Enter a window size (number of months) for rolling mean: "))
df['UserRollingMean'] = df['Passengers'].rolling(window=window).mean()
plt.figure(figsize=(10,4))
plt.plot(df['Passengers'], label='Original')
plt.plot(df['UserRollingMean'], label=f'Rolling Mean (Window={window})', color='orange')
plt.title(f'Rolling Mean with Window {window}')
plt.xlabel("Month")
plt.ylabel("Passengers")
plt.legend()
plt.show()
# Check for missing values after rolling mean.
missing = df['UserRollingMean'].isna().sum()
print(f"Missing values in UserRollingMean: {missing}")
# Fill missing values with the column's first valid value.
df['UserRollingMeanFilled'] = df['UserRollingMean'].fillna(method='bfill')
df[['UserRollingMean', 'UserRollingMeanFilled']].head(window+2)
# Rolling mean with an odd window, such as 5 months.
df['RollingMean5'] = df['Passengers'].rolling(window=5, min_periods=1).mean()
df[['Passengers', 'RollingMean5']].head(7)
Real-World Use Case#
Rolling means and EMAs are helpful in many fields:
- Stock market trends
- COVID-19 case smoothing
- Weather forecasting
- Website visitor analysis
Let us use what you have learned on a new dataset next.
# Mini project: Daily minimum temperatures dataset.
temp_url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/daily-min-temperatures.csv"
temps = pd.read_csv(temp_url)
print("Shape:", temps.shape)
temps.head()
# Plot daily temperatures for one year.
temps['Date'] = pd.to_datetime(temps['Date'])
one_year = temps[temps['Date'].dt.year == 1981]
plt.figure(figsize=(10,4))
plt.plot(one_year['Date'], one_year['Temp'], label='Daily Min Temp')
plt.title("Daily Min Temperature (1981)")
plt.xlabel("Date")
plt.ylabel("Temp (C)")
plt.legend()
plt.show()
# Compute and plot 7-day rolling mean and E M A
one_year['Rolling7'] = one_year['Temp'].rolling(window=7).mean()
one_year['EMA7'] = one_year['Temp'].ewm(span=7, adjust=False).mean()
plt.figure(figsize=(10,4))
plt.plot(one_year['Date'], one_year['Temp'], label='Daily Min Temp', alpha=0.3)
plt.plot(one_year['Date'], one_year['Rolling7'], label='7-Day Rolling Mean', color='orange')
plt.plot(one_year['Date'], one_year['EMA7'], label='EMA (Span=7)', color='green')
plt.title("7-Day Rolling Mean and E M A of Temperatures")
plt.xlabel("Date")
plt.ylabel("Temp (C)")
plt.legend()
plt.show()
Best Practices and Troubleshooting#
- Try different window sizes to see what fits your data best.
- Watch out for missing values after rolling.
- Use rolling mean for gradual trends, and EMA when you need quicker changes.
If graphs look strange, check for outliers or missing entries.
# Challenge: Ask the user for a span value for E M A calculation.
span = int(input("Enter a span (number of days) for EMA: "))
one_year['ChallengeEMA'] = one_year['Temp'].ewm(span=span, adjust=False).mean()
plt.figure(figsize=(10,4))
plt.plot(one_year['Date'], one_year['Temp'], label='Daily Min Temp', alpha=0.3)
plt.plot(one_year['Date'], one_year['ChallengeEMA'], label=f'EMA (Span={span})', color='green')
plt.title(f'Challenge: EMA with Span {span}')
plt.xlabel("Date")
plt.ylabel("Temp (C)")
plt.legend()
plt.show()
Recap#
We practiced rolling mean and exponential moving average on real data.
- Rolling mean gives equal weight to each point in the window.
- E M A responds faster to new changes.
You can quickly spot trends or sudden changes with these techniques.
Thanks and Next Steps!#
Thanks for learning with us. Try using rolling mean or EMA in your own projects.
If you liked this lesson, please subscribe and hit the bell for more beginner Python videos!
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



