How to position a legend outside the plot area in matplotlib?
I’m creating a figure with 20 separate plots (not subplots) and need to place the legend outside the plot area to the right side. I want to maintain the current axes size without reducing the figure dimensions.
Specifically, I need help with:
- How to position the legend box outside the plot area, specifically to the right side
- How to reduce the font size within the legend to make the legend box more compact
To position a legend outside the plot area in matplotlib, use the bbox_to_anchor parameter along with the loc parameter to specify the exact positioning. For right-side placement, use bbox_to_anchor=(1.05, 0.5) with loc='center left' to center the legend vertically on the right side of the plot, and reduce font size using the fontsize parameter in the legend() function to make the legend more compact.
Contents
- Basic Legend Positioning Outside Plot Area
- Right Side Positioning Techniques
- Controlling Legend Font Size
- Advanced Positioning Options
- Practical Examples with 20 Plots
- Troubleshooting Common Issues
Basic Legend Positioning Outside Plot Area
The fundamental approach to positioning legends outside the plot area in matplotlib involves using the bbox_to_anchor parameter in conjunction with the loc parameter. The bbox_to_anchor parameter specifies the coordinates where the legend should be placed relative to the axes, while the loc parameter determines where within the legend box the anchor point should be located.
When you place a legend normally using just the loc parameter, matplotlib tries to find the best position within the plot area. However, when you want to position it outside, you need to provide coordinates that extend beyond the normal plot boundaries.
import matplotlib.pyplot as plt
# Create a simple plot
plt.plot([1, 2, 3], label='Line 1')
plt.plot([3, 2, 1], label='Line 2')
# Position legend outside the plot area
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
In this example, bbox_to_anchor=(1.05, 1) places the legend just outside the top-right corner of the plot area. The coordinates are relative to the axes, where (0, 0) is the bottom-left corner and (1, 1) is the top-right corner of the plot area.
Understanding Coordinates: The
bbox_to_anchorcoordinates work on a normalized coordinate system where values between 0 and 1 fall within the plot area, while values greater than 1 or less than 0 fall outside the plot area.
Right Side Positioning Techniques
For right-side positioning of the legend, you have several effective approaches depending on your specific needs:
Centered Right Position
The most common right-side positioning centers the legend vertically:
plt.legend(bbox_to_anchor=(1.05, 0.5), loc='center left')
This places the legend center-aligned on the right side of the plot. The loc='center left' ensures that the center of the legend box is aligned with the anchor point.
Top Right Position
For top-right positioning:
plt.legend(bbox_to_anchor=(1.05, 1), loc='lower left')
This positions the legend in the upper-right corner outside the plot area.
Bottom Right Position
For bottom-right positioning:
plt.legend(bbox_to_anchor=(1.05, 0), loc='upper left')
This places the legend in the lower-right corner outside the plot area.
Multiple Legends on Right Side
If you need multiple legends on the right side, you can adjust the x-coordinate for each:
# First legend
legend1 = plt.legend(bbox_to_anchor=(1.15, 0.7), loc='center left')
# Add second legend to the right of the first
plt.legend(bbox_to_anchor=(1.15, 0.3), loc='center left', handles=legend1.legendHandles)
Controlling Legend Font Size
To make the legend box more compact, you need to reduce the font size. Here are several effective methods:
Using fontsize Parameter
The simplest approach is to use the fontsize parameter:
plt.legend(bbox_to_anchor=(1.05, 0.5), loc='center left', fontsize='small')
You can specify font size in several ways:
- String values: ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’
- Numeric values: 8, 10, 12, etc. (points)
- Relative values: ‘smaller’, ‘larger’
Using FontProperties
For more precise control, use FontProperties:
from matplotlib.font_manager import FontProperties
font_prop = FontProperties(size='small')
plt.legend(bbox_to_anchor=(1.05, 0.5), loc='center left', prop=font_prop)
Combined Font Size Control
You can control both legend text and title font sizes:
plt.legend(
bbox_to_anchor=(1.05, 0.5),
loc='center left',
fontsize='small',
title_fontsize='x-small',
labelspacing=0.5 # Reduce spacing between legend items
)
Global Font Settings
To apply consistent font sizing across all legends:
import matplotlib.pyplot as plt
# Set global legend font size
plt.rcParams['legend.fontsize'] = 'small'
plt.rcParams['legend.title_fontsize'] = 'x-small'
Advanced Positioning Options
Using Figure-Level Legends
For complex scenarios with multiple plots, consider using figure-level legends:
fig, ax = plt.subplots()
ax.plot([1, 2, 3], label='Line 1')
ax.plot([3, 2, 1], label='Line 2')
# Create figure-level legend
fig.legend(loc='center right', bbox_to_anchor=(0.95, 0.5))
plt.tight_layout() # Adjust layout to make room for legend
Dynamic Legend Positioning
For responsive positioning, you can calculate coordinates based on plot dimensions:
def position_legend_right(ax, offset=0.05, vertical_center=0.5):
"""Position legend outside the right side of the plot"""
ax.legend(
bbox_to_anchor=(1 + offset, vertical_center),
loc='center left',
fontsize='small'
)
plt.tight_layout(rect=[0, 0, 0.9, 1]) # Leave space on right
Legend with Multiple Columns
To make compact legends with many entries:
plt.legend(
bbox_to_anchor=(1.05, 0.5),
loc='center left',
fontsize='small',
ncol=2, # Two columns
framealpha=0.9 # Slightly transparent background
)
Practical Examples with 20 Plots
Creating 20 Separate Plots
When working with 20 separate plots, you need a systematic approach:
import matplotlib.pyplot as plt
import numpy as np
# Create figure with proper spacing
fig, axes = plt.subplots(4, 5, figsize=(20, 16))
fig.suptitle('20 Separate Plots with External Legends', fontsize=16)
# Generate random data for each plot
x = np.linspace(0, 10, 100)
for i, ax in enumerate(axes.flat):
# Create different data for each plot
y1 = np.sin(x + i * 0.5)
y2 = np.cos(x + i * 0.5)
ax.plot(x, y1, label=f'Sine {i+1}')
ax.plot(x, y2, label=f'Cosine {i+1}')
# Position legend outside to the right
ax.legend(
bbox_to_anchor=(1.15, 0.5),
loc='center left',
fontsize='x-small',
framealpha=0.8
)
ax.set_title(f'Plot {i+1}', fontsize='small')
ax.grid(True, alpha=0.3)
# Adjust layout to accommodate external legends
plt.tight_layout()
plt.subplots_adjust(right=0.85) # Make room for legends on the right
plt.show()
Optimized Legend Layout
For better organization with many legends:
def create_optimized_legend_grid(fig, axes, positions='right'):
"""Create optimized legend arrangement for multiple plots"""
if positions == 'right':
# Collect all legend handles and labels from all axes
all_handles = []
all_labels = []
for ax in axes.flat:
handles, labels = ax.get_legend_handles_labels()
all_handles.extend(handles)
all_labels.extend(labels)
# Create a single legend for all plots
legend = fig.legend(
all_handles,
all_labels,
bbox_to_anchor=(0.98, 0.5),
loc='center left',
fontsize='small',
ncol=1,
framealpha=0.9
)
# Adjust layout to make room for the legend
plt.tight_layout(rect=[0, 0, 0.92, 1])
return legend
elif positions == 'separate':
# Position individual legends
for i, ax in enumerate(axes.flat):
ax.legend(
bbox_to_anchor=(1.05 + (i % 5) * 0.1, 0.95 - (i // 5) * 0.2),
loc='upper left',
fontsize='x-small'
)
plt.tight_layout(rect=[0, 0, 0.85, 1])
Troubleshooting Common Issues
Legend Cutoff Issues
When legends get cutoff, these solutions help:
# Method 1: Use tight_layout with adjustment
plt.tight_layout(rect=[0, 0, 0.9, 1])
# Method 2: Use constrained layout
plt.rcParams['figure.constrained_layout.use'] = True
# Method 3: Adjust subplot parameters
plt.subplots_adjust(right=0.85)
Legend Overlap with Plot Elements
To prevent overlap with plot elements:
# Increase plot margins
ax.margins(0.1)
# Or adjust plot limits to make more space
ax.set_xlim(left=0.1, right=0.9)
Legend Box Size Optimization
For optimal legend box size:
plt.legend(
bbox_to_anchor=(1.05, 0.5),
loc='center left',
fontsize='small',
borderpad=0.2, # Reduce border padding
labelspacing=0.3, # Reduce spacing between items
handlelength=1.5, # Reduce handle length
handletextpad=0.3 # Reduce space between handle and text
)
Responsive Legend Positioning
For responsive design that works across different figure sizes:
def responsive_legend_position(ax, position='right', margin=0.1):
"""Create responsive legend positioning"""
if position == 'right':
# Calculate position based on axes size
bbox = ax.get_position()
x_pos = bbox.x1 + margin * bbox.width
y_pos = bbox.y0 + 0.5 * bbox.height
ax.legend(
bbox_to_anchor=(x_pos, y_pos),
loc='center left',
fontsize='small'
)
By combining these techniques—right-side positioning using bbox_to_anchor and font size control using fontsize or FontProperties—you can effectively place legends outside your plot areas while maintaining compact, readable legend boxes that don’t interfere with your data visualization.
Sources
- Matplotlib Legend Guide - Official Documentation
- How to Place Legend Outside of the Plot in Matplotlib - GeeksforGeeks
- Python - How to put the legend outside the plot - Stack Overflow
- How to Change Legend Font Size in Matplotlib - Statology
- Matplotlib.pyplot.legend - Official API Documentation
- Enhancing Data Visualization: Moving Legends Outside the Plot with Matplotlib
- Python 🐍 Put Legend Outside Plot 📈 – Easy Guide
Conclusion
Positioning legends outside the plot area in matplotlib, particularly to the right side, is straightforward using the bbox_to_anchor and loc parameters together. For right-side placement, bbox_to_anchor=(1.05, 0.5) with loc='center left' provides optimal vertical centering. To create more compact legend boxes, use the fontsize='small' or fontsize='x-small' parameters, or employ FontProperties for precise control. When working with multiple plots like 20 separate figures, consider using figure-level legends or systematic positioning with tight_layout() adjustments to maintain proper spacing and prevent overlap. These techniques ensure your legends remain readable and don’t interfere with your data visualization while keeping your axes at their current dimensions.