How to Create an Area Chart in Matplotlib
Area charts are line charts with the area between the line and axis filled with color. They're particularly effective when you need to emphasize the magnitude of change over time, not just the trend...
Key Insights
- Area charts excel at showing volume and cumulative trends over time, making them ideal for metrics like revenue, traffic, or resource utilization where the magnitude matters as much as the trend
- The
fill_between()function is your primary tool in Matplotlib, offering precise control over fills, colors, and transparency to create both single and stacked area visualizations - Transparency (alpha values between 0.3-0.7) is critical for overlapping area charts to prevent data occlusion, while stacked charts work best with 3-5 categories maximum to maintain readability
Introduction to Area Charts
Area charts are line charts with the area between the line and axis filled with color. They’re particularly effective when you need to emphasize the magnitude of change over time, not just the trend direction. Unlike line charts that focus on the trajectory, area charts draw attention to the volume or cumulative total represented by the data.
Use area charts when you’re visualizing quantities that accumulate, such as total revenue over time, server resource usage, or website traffic patterns. They’re especially powerful for showing part-to-whole relationships through stacked variations, where multiple data series combine to show both individual contributions and the total sum.
The filled area provides immediate visual weight that helps viewers understand scale at a glance. This makes area charts superior to line charts when the absolute values matter as much as the trend—think of showing the growing user base of a platform or the increasing storage consumption in a database.
Basic Area Chart
Matplotlib’s fill_between() function is the foundation for creating area charts. It fills the area between two y-values (typically between your data line and zero) across a range of x-values.
import matplotlib.pyplot as plt
import numpy as np
# Sample data: monthly website traffic
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
traffic = [12500, 15200, 18400, 22100, 26800, 31200,
35400, 38900, 42300, 39800, 43500, 47200]
# Create the area chart
fig, ax = plt.subplots(figsize=(10, 6))
ax.fill_between(range(len(months)), traffic, alpha=0.7, color='#2E86AB')
ax.plot(range(len(months)), traffic, color='#023E73', linewidth=2)
# Basic formatting
ax.set_xticks(range(len(months)))
ax.set_xticklabels(months)
ax.set_ylabel('Visitors', fontsize=12)
ax.set_title('Monthly Website Traffic', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()
The alpha parameter controls transparency (0.7 gives a nice balance between visibility and depth). Adding a darker line on top with plot() creates a clear boundary that helps readers trace the exact values.
Stacked Area Charts
Stacked area charts show multiple data series that combine to form a total. Each layer represents a component of the whole, making it easy to see both individual trends and the cumulative effect.
import matplotlib.pyplot as plt
import numpy as np
# Revenue data by product category (in thousands)
months = np.arange(1, 13)
software = np.array([45, 48, 52, 58, 62, 68, 72, 75, 78, 82, 85, 90])
consulting = np.array([30, 32, 35, 38, 40, 42, 45, 48, 50, 52, 55, 58])
support = np.array([15, 16, 18, 20, 22, 25, 28, 30, 32, 35, 38, 42])
training = np.array([10, 11, 12, 14, 16, 18, 20, 22, 25, 28, 30, 33])
fig, ax = plt.subplots(figsize=(12, 7))
# Stack the areas from bottom to top
ax.fill_between(months, 0, training, alpha=0.8, color='#E63946', label='Training')
ax.fill_between(months, training, training + support, alpha=0.8,
color='#F4A261', label='Support')
ax.fill_between(months, training + support, training + support + consulting,
alpha=0.8, color='#2A9D8F', label='Consulting')
ax.fill_between(months, training + support + consulting,
training + support + consulting + software,
alpha=0.8, color='#264653', label='Software')
# Formatting
ax.set_xlabel('Month', fontsize=12)
ax.set_ylabel('Revenue ($K)', fontsize=12)
ax.set_title('Revenue Breakdown by Product Category', fontsize=14, fontweight='bold')
ax.legend(loc='upper left', frameon=True, shadow=True)
ax.set_xlim(1, 12)
plt.tight_layout()
plt.show()
The key technique here is cumulative addition: each layer starts where the previous one ended. This creates the stacked effect. Keep the number of categories limited (3-5 maximum) to avoid a cluttered visualization that’s hard to interpret.
Customizing Appearance
Fine-tuning colors, transparency, and borders transforms basic area charts into polished visualizations that align with your brand or presentation needs.
import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
x = np.linspace(0, 10, 100)
y = 3 + 2 * np.sin(x) + np.random.normal(0, 0.2, 100)
fig, ax = plt.subplots(figsize=(12, 6))
# Create gradient effect by layering multiple fills with varying alpha
for i in range(5):
alpha_value = 0.15 * (5 - i)
y_offset = y - (i * 0.3)
ax.fill_between(x, y_offset, alpha=alpha_value, color='#6A4C93')
# Add main area with custom color
ax.fill_between(x, y, alpha=0.4, color='#6A4C93', label='Data Range')
# Add edge line with different color and style
ax.plot(x, y, color='#1982C4', linewidth=2.5, linestyle='-', label='Trend Line')
# Styling
ax.set_xlabel('Time Period', fontsize=12, fontweight='bold')
ax.set_ylabel('Metric Value', fontsize=12, fontweight='bold')
ax.set_title('Customized Area Chart with Gradient Effect',
fontsize=14, fontweight='bold', pad=20)
ax.legend(loc='upper right', framealpha=0.9)
ax.grid(True, alpha=0.3, linestyle='--')
ax.set_facecolor('#F8F9FA')
plt.tight_layout()
plt.show()
The gradient effect is achieved by layering multiple fill_between() calls with progressively lower alpha values and slight y-offsets. This creates visual depth without overwhelming the chart. The contrasting edge line color helps the data stand out against the filled area.
Multiple Overlapping Area Charts
When comparing separate data series that don’t stack, overlapping area charts with transparency let viewers see all series simultaneously while understanding their relative magnitudes.
import matplotlib.pyplot as plt
import numpy as np
# Sales data for three regions
months = np.arange(1, 13)
north_america = np.array([85, 88, 92, 95, 98, 102, 105, 108, 112, 115, 118, 122])
europe = np.array([72, 75, 78, 82, 85, 88, 92, 95, 98, 102, 105, 108])
asia_pacific = np.array([45, 52, 58, 65, 72, 80, 88, 95, 103, 110, 118, 125])
fig, ax = plt.subplots(figsize=(12, 7))
# Create overlapping areas with transparency
ax.fill_between(months, north_america, alpha=0.5, color='#E63946', label='North America')
ax.fill_between(months, europe, alpha=0.5, color='#2A9D8F', label='Europe')
ax.fill_between(months, asia_pacific, alpha=0.5, color='#F4A261', label='Asia Pacific')
# Add border lines for clarity
ax.plot(months, north_america, color='#A4161A', linewidth=2)
ax.plot(months, europe, color='#1B7F75', linewidth=2)
ax.plot(months, asia_pacific, color='#D68A4D', linewidth=2)
# Formatting
ax.set_xlabel('Month', fontsize=12, fontweight='bold')
ax.set_ylabel('Sales ($M)', fontsize=12, fontweight='bold')
ax.set_title('Regional Sales Comparison', fontsize=14, fontweight='bold', pad=20)
ax.legend(loc='upper left', fontsize=11, framealpha=0.9)
ax.grid(True, alpha=0.3, axis='y')
ax.set_xlim(1, 12)
plt.tight_layout()
plt.show()
The alpha value of 0.5 is crucial here—it’s transparent enough to see overlapping areas but opaque enough to distinguish each series. Border lines in slightly darker shades of the fill colors provide definition without adding visual noise.
Adding Context and Annotations
A chart without context is just colored shapes. Labels, legends, and annotations transform data visualizations into communication tools.
import matplotlib.pyplot as plt
import numpy as np
# Quarterly revenue data
quarters = ['Q1\n2023', 'Q2\n2023', 'Q3\n2023', 'Q4\n2023',
'Q1\n2024', 'Q2\n2024', 'Q3\n2024', 'Q4\n2024']
revenue = [145, 158, 172, 195, 210, 225, 248, 275]
fig, ax = plt.subplots(figsize=(12, 7))
# Create area chart
ax.fill_between(range(len(quarters)), revenue, alpha=0.6, color='#2E86AB')
ax.plot(range(len(quarters)), revenue, color='#023E73',
linewidth=2.5, marker='o', markersize=8, markerfacecolor='white',
markeredgewidth=2, markeredgecolor='#023E73')
# Add annotation for significant milestone
peak_idx = 7
ax.annotate('Record Quarter\n$275M Revenue',
xy=(peak_idx, revenue[peak_idx]),
xytext=(peak_idx - 1.5, revenue[peak_idx] + 30),
fontsize=11, fontweight='bold', color='#023E73',
arrowprops=dict(arrowstyle='->', color='#023E73', lw=2),
bbox=dict(boxstyle='round,pad=0.5', facecolor='white',
edgecolor='#023E73', linewidth=2))
# Comprehensive formatting
ax.set_xticks(range(len(quarters)))
ax.set_xticklabels(quarters, fontsize=10)
ax.set_ylabel('Revenue ($M)', fontsize=12, fontweight='bold')
ax.set_title('Company Revenue Growth (2023-2024)',
fontsize=14, fontweight='bold', pad=20)
ax.grid(True, alpha=0.3, linestyle='--', axis='y')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.set_ylim(0, max(revenue) + 50)
plt.tight_layout()
plt.show()
Annotations guide the viewer’s attention to important data points. The annotate() function creates arrows pointing to specific values with explanatory text. Removing the top and right spines creates a cleaner, more modern look that focuses attention on the data itself.
Common Pitfalls and Best Practices
Avoid too many stacked categories. More than five layers becomes difficult to interpret. If you have more categories, consider grouping smaller ones into an “Other” category or using a different chart type.
Choose alpha values carefully. For single area charts, 0.6-0.8 works well. For overlapping charts, use 0.4-0.6. For stacked charts, you can go higher (0.8-0.9) since there’s no overlap.
Handle negative values explicitly. By default, fill_between() fills to zero. If your data includes negative values, specify both y1 and y2 parameters to control exactly what area gets filled.
Don’t use area charts for precise value comparison. The filled area can make it harder to read exact values compared to line or bar charts. Area charts are about showing magnitude and trends, not precise point-in-time comparisons.
Consider your baseline carefully. Starting the y-axis at zero is usually essential for area charts since the filled area implies magnitude from the baseline. Starting above zero can create misleading visual impressions about the data’s scale.
Use color strategically. For stacked area charts, order categories from most stable (bottom) to most volatile (top), and use color progression (light to dark or sequential colormap) to guide the eye naturally through the layers.
Area charts are powerful tools for showing volume and cumulative trends, but they require thoughtful design choices to communicate effectively. Master these techniques, and you’ll create visualizations that not only display data but tell compelling stories about what that data means.