НейроАгент

Размещение легенды вне графика в Matplotlib

Узнайте, как размещать легенды вне областей графиков в matplotlib справа, сохраняя размеры осей. Уменьшите размер шрифта легенды для компактного отображения с помощью нашего полного руководства.

Вопрос

Как разместить легенду за пределами области графика в matplotlib?

Я создаю фигуру с 20 отдельными графиками (не подграфиками) и мне нужно разместить легенду снаружи области графика справа. Я хочу сохранить текущий размер осей без уменьшения размеров фигуры.

Конкретно мне нужна помощь с:

  1. Как разместить рамку легенды за пределами области графика, конкретно справа
  2. Как уменьшить размер шрифта в легенде, чтобы сделать рамку легенды более компактной
НейроАгент

Чтобы разместить легенду за пределами области построения в matplotlib, используйте параметр bbox_to_anchor вместе с параметром loc для указания точного позиционирования. Для размещения справа используйте bbox_to_anchor=(1.05, 0.5) с loc='center left', чтобы центрировать легенду вертикально справа от графика, и уменьшите размер шрифта с помощью параметра fontsize в функции legend(), чтобы сделать легенду более компактной.

Содержание

Базовое позиционирование легенды за пределами области построения

Основной подход к позиционированию легенды за пределами области построения в matplotlib включает использование параметра bbox_to_anchor в сочетании с параметром loc. Параметр bbox_to_anchor задает координаты, где должна быть размещена легенда относительно осей, в то время как параметр loc определяет, где внутри рамки легенды должна находиться точка привязки.

Когда вы размещаете легенду обычным способом, используя только параметр loc, matplotlib пытается найти лучшее положение внутри области построения. Однако, когда вы хотите разместить ее снаружи, вам нужно предоставить координаты, которые выходят за обычные границы графика.

python
import matplotlib.pyplot as plt

# Создаем простой график
plt.plot([1, 2, 3], label='Линия 1')
plt.plot([3, 2, 1], label='Линия 2')

# Размещаем легенду за пределами области построения
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()

В этом примере bbox_to_anchor=(1.05, 1) размещает легенду чуть в правом верхнем углу за пределами области построения. Координаты относительны осям, где (0, 0) - левый нижний угол, а (1, 1) - правый верхний угол области построения.

Понимание координат: Координаты bbox_to_anchor работают в нормализованной системе координат, где значения между 0 и 1 попадают внутрь области построения, в то время как значения больше 1 или меньше 0 находятся за ее пределами.

Техники размещения легенды справа

Для размещения легенды справа у вас есть несколько эффективных подходов в зависимости от ваших конкретных потребностей:

Центрированное размещение справа

Наиболее распространенное размещение справа центрирует легенду по вертикали:

python
plt.legend(bbox_to_anchor=(1.05, 0.5), loc='center left')

Это размещает легенду по центру справа от графика. Параметр loc='center left' гарантирует, что центр рамки легенды выровнен по точке привязки.

Размещение в правом верхнем углу

Для размещения в правом верхнем углу:

python
plt.legend(bbox_to_anchor=(1.05, 1), loc='lower left')

Это размещает легенду в правом верхнем углу за пределами области построения.

Размещение в правом нижнем углу

Для размещения в правом нижнем углу:

python
plt.legend(bbox_to_anchor=(1.05, 0), loc='upper left')

Это размещает легенду в правом нижнем углу за пределами области построения.

Несколько легенд справа

Если вам нужно несколько легенд справа, вы можете настроить x-координату для каждой:

python
# Первая легенда
legend1 = plt.legend(bbox_to_anchor=(1.15, 0.7), loc='center left')

# Добавляем вторую легенду справа от первой
plt.legend(bbox_to_anchor=(1.15, 0.3), loc='center left', handles=legend1.legendHandles)

Управление размером шрифта легенды

Чтобы сделать рамку легенды более компактной, вам нужно уменьшить размер шрифта. Вот несколько эффективных методов:

Использование параметра fontsize

Простой подход - использовать параметр fontsize:

python
plt.legend(bbox_to_anchor=(1.05, 0.5), loc='center left', fontsize='small')

Вы можете указать размер шрифта несколькими способами:

  • Строковые значения: ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’
  • Числовые значения: 8, 10, 12 и т.д. (в пунктах)
  • Относительные значения: ‘smaller’, ‘larger’

Использование FontProperties

Для более точного контроля используйте 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)

Комбинированный контроль размера шрифта

Вы можете контролировать как размер шрифта текста легенды, так и размер шрифта заголовка:

python
plt.legend(
    bbox_to_anchor=(1.05, 0.5),
    loc='center left',
    fontsize='small',
    title_fontsize='x-small',
    labelspacing=0.5  # Уменьшаем интервал между элементами легенды
)

Глобальные настройки шрифта

Для применения согласованного размера шрифта ко всем легендам:

python
import matplotlib.pyplot as plt

# Устанавливаем глобальный размер шрифта легенды
plt.rcParams['legend.fontsize'] = 'small'
plt.rcParams['legend.title_fontsize'] = 'x-small'

Расширенные варианты позиционирования

Использование легенд на уровне фигуры

Для сложных сценариев с несколькими графиками рассмотрите возможность использования легенд на уровне фигуры:

python
fig, ax = plt.subplots()
ax.plot([1, 2, 3], label='Линия 1')
ax.plot([3, 2, 1], label='Линия 2')

# Создаем легенду на уровне фигуры
fig.legend(loc='center right', bbox_to_anchor=(0.95, 0.5))
plt.tight_layout()  # Корректируем расположение, чтобы освободить место для легенды

Динамическое позиционирование легенды

Для адаптивного позиционирования вы можете вычислять координаты на основе размеров графика:

python
def position_legend_right(ax, offset=0.05, vertical_center=0.5):
    """Размещаем легенду снаружи справа от графика"""
    ax.legend(
        bbox_to_anchor=(1 + offset, vertical_center),
        loc='center left',
        fontsize='small'
    )
    plt.tight_layout(rect=[0, 0, 0.9, 1])  # Оставляем место справа

Легенда с несколькими столбцами

Для создания компактных легенд с большим количеством записей:

python
plt.legend(
    bbox_to_anchor=(1.05, 0.5),
    loc='center left',
    fontsize='small',
    ncol=2,  # Два столбца
    framealpha=0.9  # Незначительно прозрачный фон
)

Практические примеры с 20 графиками

Создание 20 отдельных графиков

При работе с 20 отдельными графиками вам нужен систематический подход:

python
import matplotlib.pyplot as plt
import numpy as np

# Создаем фигуру с правильными отступами
fig, axes = plt.subplots(4, 5, figsize=(20, 16))
fig.suptitle('20 отдельных графиков с внешними легендами', fontsize=16)

# Генерируем случайные данные для каждого графика
x = np.linspace(0, 10, 100)

for i, ax in enumerate(axes.flat):
    # Создаем разные данные для каждого графика
    y1 = np.sin(x + i * 0.5)
    y2 = np.cos(x + i * 0.5)
    
    ax.plot(x, y1, label=f'Синус {i+1}')
    ax.plot(x, y2, label=f'Косинус {i+1}')
    
    # Размещаем легенду справа снаружи
    ax.legend(
        bbox_to_anchor=(1.15, 0.5),
        loc='center left',
        fontsize='x-small',
        framealpha=0.8
    )
    
    ax.set_title(f'График {i+1}', fontsize='small')
    ax.grid(True, alpha=0.3)

# Корректируем расположение, чтобы accommodate внешние легенды
plt.tight_layout()
plt.subplots_adjust(right=0.85)  # Освобождаем место справа для легенд
plt.show()

Оптимизированное расположение легенды

Для лучшей организации с множеством легенд:

python
def create_optimized_legend_grid(fig, axes, positions='right'):
    """Создаем оптимизированное расположение легенд для нескольких графиков"""
    
    if positions == 'right':
        # Собираем все маркеры и метки легенд со всех осей
        all_handles = []
        all_labels = []
        
        for ax in axes.flat:
            handles, labels = ax.get_legend_handles_labels()
            all_handles.extend(handles)
            all_labels.extend(labels)
        
        # Создаем одну легенду для всех графиков
        legend = fig.legend(
            all_handles,
            all_labels,
            bbox_to_anchor=(0.98, 0.5),
            loc='center left',
            fontsize='small',
            ncol=1,
            framealpha=0.9
        )
        
        # Корректируем расположение, чтобы освободить место для легенды
        plt.tight_layout(rect=[0, 0, 0.92, 1])
        
        return legend
    
    elif positions == 'separate':
        # Размещаем отдельные легенды
        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])

Устранение распространенных проблем

Проблемы с обрезкой легенды

Когда легенды обрезаются, эти решения помогают:

python
# Метод 1: Используем tight_layout с корректировкой
plt.tight_layout(rect=[0, 0, 0.9, 1])

# Метод 2: Используем constrained_layout
plt.rcParams['figure.constrained_layout.use'] = True

# Метод 3: Корректируем параметры подграфика
plt.subplots_adjust(right=0.85)

Перекрытие легенды с элементами графика

Чтобы предотвратить перекрытие с элементами графика:

python
# Увеличиваем поля графика
ax.margins(0.1)

# Или корректируем пределы графика, чтобы освободить больше места
ax.set_xlim(left=0.1, right=0.9)

Оптимизация размера рамки легенды

Для оптимального размера рамки легенды:

python
plt.legend(
    bbox_to_anchor=(1.05, 0.5),
    loc='center left',
    fontsize='small',
    borderpad=0.2,      # Уменьшаем отступ рамки
    labelspacing=0.3,   # Уменьшаем интервал между элементами
    handlelength=1.5,   # Уменьшаем длину маркера
    handletextpad=0.3   # Уменьшаем пространство между маркером и текстом
)

Адаптивное позиционирование легенды

Для адаптивного дизайна, который работает с разными размерами фигур:

python
def responsive_legend_position(ax, position='right', margin=0.1):
    """Создаем адаптивное позиционирование легенды"""
    if position == 'right':
        # Вычисляем позицию на основе размера осей
        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'
        )

Комбинируя эти техники - размещение справа с использованием bbox_to_anchor и контроль размера шрифта с помощью fontsize или FontProperties - вы можете эффективно размещать легенды за пределами областей построения, сохраняя при этом компактные, читаемые рамки легенд, которые не мешают визуализации данных.

Источники

  1. Руководство по легенде Matplotlib - Официальная документация
  2. Как разместить легенду вне графика в Matplotlib - GeeksforGeeks
  3. Python - Как поместить легенду вне графика - Stack Overflow
  4. Как изменить размер шрифта легенды в Matplotlib - Statology
  5. Matplotlib.pyplot.legend - Официальная документация API
  6. Улучшение визуализации данных: Перемещение легенды вне графика с Matplotlib
  7. Python 🐍 Размещение легенды вне графика 📈 – Простое руководство

Заключение

Размещение легенды за пределами области построения в matplotlib, особенно справа, осуществляется просто с помощью совместного использования параметров bbox_to_anchor и loc. Для размещения справа bbox_to_anchor=(1.05, 0.5) с loc='center left' обеспечивает оптимальное вертикальное центрирование. Чтобы создать более компактные рамки легенды, используйте параметры fontsize='small' или fontsize='x-small', или применяйте FontProperties для точного контроля. При работе с несколькими графиками, такими как 20 отдельных фигур, рассмотрите возможность использования легенд на уровне фигуры или систематического позиционирования с корректировками tight_layout(), чтобы поддерживать правильные интервалы и предотвращать перекрытие. Эти методы гарантируют, что ваши легенды остаются читаемыми и не мешают визуализации данных, сохраняя при этом текущие размеры осей.