NeuroAgent

Position Legend Outside Plot in Matplotlib

Learn how to position legends outside plot areas in matplotlib to the right side while maintaining axes size. Reduce legend font size for compact display with our complete guide.

Question

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:

  1. How to position the legend box outside the plot area, specifically to the right side
  2. How to reduce the font size within the legend to make the legend box more compact
NeuroAgent

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

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.

python
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_anchor coordinates 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:

python
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:

python
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:

python
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:

python
# 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:

python
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:

python
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:

python
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:

python
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:

python
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:

python
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:

python
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:

python
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:

python
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:

python
# 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:

python
# 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:

python
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:

python
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

  1. Matplotlib Legend Guide - Official Documentation
  2. How to Place Legend Outside of the Plot in Matplotlib - GeeksforGeeks
  3. Python - How to put the legend outside the plot - Stack Overflow
  4. How to Change Legend Font Size in Matplotlib - Statology
  5. Matplotlib.pyplot.legend - Official API Documentation
  6. Enhancing Data Visualization: Moving Legends Outside the Plot with Matplotlib
  7. 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.