Create a Matplotlib Boxplot for Time Series Data in Python

I’ve found that a single line chart often hides the most important parts of a story. When you are dealing with time series data, showing just the average or the trend line isn’t enough to see the full picture.

You often need to see the “spread” or the volatility of that data over specific intervals, like months or years. This is where the boxplot comes in handy, especially when applied to time-indexed information.

In this tutorial, I will show you exactly how I create and customize Matplotlib boxplots for time series data using real-world USA-based examples.

Use a Boxplot for Time Series

Standard time series plots are great for showing trends, but they fail to show the distribution of values within a timeframe.

For instance, if you’re looking at daily temperature fluctuations in New York City over a year, a line chart only shows the daily highs or lows.

A boxplot allows you to see the median, quartiles, and outliers for each month at a glance.

It helps me quickly identify which months have the most volatile weather or which stock trading weeks have had the highest price swings.

Method 1: Create a Monthly Boxplot for USA Stock Trends

One of the most common tasks I handle is analyzing stock market volatility.

In this example, we will simulate a year of trading data for a US-based tech company and group it by month to see the price distribution.

I prefer using pandas alongside matplotlib because it makes handling date objects incredibly easy.

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# Setting a seed for reproducibility
np.random.seed(42)

# Generate a date range for one year of US trading days
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='B')

# Simulate stock prices with a random walk
price_changes = np.random.normal(0, 1, len(dates))
prices = 150 + np.cumsum(price_changes) # Starting price of $150

# Create a DataFrame
df = pd.DataFrame({'Date': dates, 'Price': prices})

# Extract the month name for grouping
df['Month'] = df['Date'].dt.strftime('%b')
df['Month_Num'] = df['Date'].dt.month
df = df.sort_values('Month_Num')

# Prepare the data for Matplotlib
# I'm grouping the prices into a list of arrays, one for each month
data_to_plot = [df[df['Month'] == month]['Price'] for month in df['Month'].unique()]
labels = df['Month'].unique()

# Initialize the plot
plt.figure(figsize=(12, 6))

# Creating the boxplot
plt.boxplot(data_to_plot, labels=labels, patch_artist=True,
            boxprops=dict(facecolor='#e6f2ff', color='#004080'),
            medianprops=dict(color='red'))

# Adding titles and labels
plt.title('Monthly Stock Price Distribution - TechCorp (USA)', fontsize=14)
plt.xlabel('Month (2023)', fontsize=12)
plt.ylabel('Price (USD)', fontsize=12)
plt.grid(axis='y', linestyle='--', alpha=0.7)

# Show the plot
plt.show()

I executed the above example code and added the screenshot below.

Matplotlib Boxplot for Time Series Data in Python

In this code, I first generated a year’s worth of business days to represent a typical US trading calendar. I used the dt.strftime(‘%b’) method to group the data into months like “Jan”, “Feb”, and so on.

By passing a list of arrays to plt.boxplot(), Matplotlib automatically aligns each box with its corresponding month.

I also used patch_artist=True to fill the boxes with color, which makes the chart much easier to read during presentations.

Method 2: Visualize Seasonal Temperature Variance

I often work with environmental data, such as temperatures in various US regions. In this scenario, we want to see how temperatures vary across different seasons in the Midwest.

Instead of just months, we can group the data by season to see the “extremes” that occur during the American winter versus summer.

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# Generate daily data for 2 years
dates = pd.date_range(start='2022-01-01', end='2023-12-31', freq='D')

# Simulate temperatures with seasonal sine wave + noise
# Average 50 degrees F, with 30 degree seasonal swing
temps = 50 + 30 * np.sin(2 * np.pi * (dates.dayofyear / 365.25 - 0.25)) + np.random.normal(0, 5, len(dates))

df_weather = pd.DataFrame({'Date': dates, 'Temp': temps})

# Function to map months to US Seasons
def get_season(month):
    if month in [12, 1, 2]: return 'Winter'
    elif month in [3, 4, 5]: return 'Spring'
    elif month in [6, 7, 8]: return 'Summer'
    else: return 'Fall'

df_weather['Season'] = df_weather['Date'].dt.month.map(get_season)

# Order the seasons for the plot
season_order = ['Winter', 'Spring', 'Summer', 'Fall']
data_seasons = [df_weather[df_weather['Season'] == s]['Temp'] for s in season_order]

# Create the plot
fig, ax = plt.subplots(figsize=(10, 6))

# Customizing the look
bplot = ax.boxplot(data_seasons, labels=season_order, patch_artist=True)

# Define US-inspired colors for seasons
colors = ['#ADD8E6', '#90EE90', '#FFD700', '#FF8C00'] # LightBlue, LightGreen, Gold, DarkOrange

for patch, color in zip(bplot['boxes'], colors):
    patch.set_facecolor(color)

plt.title('Daily Temperature Distribution by Season (Midwest USA)', fontsize=14)
plt.ylabel('Temperature (°F)', fontsize=12)
plt.xlabel('Season', fontsize=12)
plt.grid(linestyle=':', alpha=0.6)

plt.show()

I executed the above example code and added the screenshot below.

Create Matplotlib Boxplot for Time Series Data in Python

When I create these charts for clients, I always try to use colors that intuitively represent the data.

Notice how I used blue for Winter and orange for Fall; this helps the viewer understand the data before they even read the labels.

Using the zip function to iterate through the bplot[‘boxes’] is the cleanest way I’ve found to apply individual colors to each box.

Method 3: Handle High-Frequency Data (Hourly Load)

If you are working with US energy markets (like ERCOT in Texas), you might be looking at hourly power demand. Boxplots are perfect for showing “Peak Hours.”

Instead of plotting every single hour, we can group data by “Time of Day” to see when the demand spikes occur.

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# Generate 3 months of hourly energy data
dates = pd.date_range(start='2023-06-01', end='2023-08-31', freq='H')

# Simulate energy load in Megawatts (MW)
# Higher load during the day, peaking in afternoon
hour_effect = np.array([10, 8, 7, 7, 8, 12, 18, 25, 30, 32, 35, 38, 40, 42, 45, 44, 42, 38, 30, 25, 20, 18, 15, 12])
load = [hour_effect[d.hour] + np.random.normal(0, 3) for d in dates]

df_energy = pd.DataFrame({'Timestamp': dates, 'Load_MW': load})
df_energy['Hour'] = df_energy['Timestamp'].dt.hour

# Prepare data
hourly_data = [df_energy[df_energy['Hour'] == h]['Load_MW'] for h in range(24)]

# Create the plot
plt.figure(figsize=(14, 7))
plt.boxplot(hourly_data, tick_labels=range(24))

plt.title('USA Regional Grid Load Distribution by Hour (Summer Months)', fontsize=14)
plt.xlabel('Hour of Day (24-hour clock)', fontsize=12)
plt.ylabel('Load (MW)', fontsize=12)
plt.xticks(range(1, 25), [f"{h}:00" for h in range(24)], rotation=45)
plt.tight_layout()

plt.show()

I executed the above example code and added the screenshot below.

Python Matplotlib Boxplot for Time Series Data

This specific visualization shows the interquartile range of electricity usage.

In my experience, this is far more valuable than a line chart because it shows the “tail risk”, those outliers where the load was unexpectedly high.

The plt.xticks rotation is a small trick I use to keep the labels from overlapping when dealing with 24 different data points.

Common Mistakes to Avoid

In my early days, I made a few mistakes that I want to help you avoid.

First, don’t forget to sort your data. If your months appear as “April, August, December” (alphabetical), your time series will make no sense. Always sort by the month number.

Second, be careful with outliers. By default, Matplotlib shows them as small circles (fliers).

If you have thousands of data points, these circles can clutter the chart. You can hide them using showfliers=False inside the boxplot function.

How to Customize Outliers and Medians

If you want your chart to stand out, you can customize every part of the box.

I often change the “flier” (outlier) style to red crosses to make them look more like “warnings.”

plt.boxplot(data_to_plot, 
            flierprops={'marker': 'x', 'markeredgecolor': 'red'},
            medianprops={'linewidth': 2, 'color': 'darkgreen'})

This level of detail is what separates a basic script from a professional dashboard. Using boxplots for time series has changed how I present data to my stakeholders.

It provides a level of depth that standard plots simply cannot match. I hope you found this tutorial useful! I have tried to cover the most common scenarios I encounter in my daily work.

You may also like to read other tutorials:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.