Как вынести легенду за пределы графика в Python: 4 способа
Для кого эта статья:
- Разработчики и дата-аналитики, использующие Python для визуализации данных
- Студенты и профессионалы, интересующиеся улучшением навыков в области графиков и визуализации
Лица, занимающиеся научными публикациями или бизнес-отчетами, которым важно создать визуализации высокого качества
Легенда — неотъемлемый элемент информативного графика, но нередко она становится "камнем преткновения" при визуализации данных. Когда ваш график насыщен важными деталями, а легенда беспардонно перекрывает ключевые области, приходит время освоить искусство выноса легенды за границы основной области построения. Python и matplotlib предоставляют несколько мощных техник, позволяющих элегантно решить эту проблему, сохранив и даже улучшив восприятие данных. Профессиональное размещение легенды — признак опытного разработчика, который учитывает каждую деталь своих визуализаций. 🚀
Хотите полностью освоить создание профессиональных визуализаций данных с помощью Python? Курс Обучение Python-разработке от Skypro погружает вас в мир настоящей разработки, где вы научитесь не только основам языка, но и продвинутым инструментам анализа и отображения данных. От базовых графиков до интерактивных дашбордов — ваши визуализации станут непревзойденными! Программа выстроена от простого к сложному с реальными проектами в портфолио.
Зачем выносить легенду за границы графика в Python
Размещение легенды внутри графика может создавать множество проблем, особенно когда данных много или они распределены по всему пространству визуализации. Умение выносить легенду за пределы основной области построения — это не просто вопрос эстетики, но и функциональности ваших визуализаций. 📊
Существует несколько объективных причин, почему стоит осваивать эту технику:
- Предотвращение перекрытия данных — легенда внутри графика может скрывать важные точки данных, тренды или выбросы.
- Улучшение читаемости — когда легенда размещена в стороне, увеличивается полезное пространство для отображения самих данных.
- Профессиональный вид — научные публикации и бизнес-отчеты часто требуют размещения легенды вне основного пространства графика.
- Возможность создания единой легенды для нескольких субграфиков.
Антон Седов, ведущий дата-аналитик
Однажды мне пришлось готовить презентацию для руководства по результатам исследования поведения пользователей нашего продукта. Я создал график, отображающий 8 различных метрик активности по дням недели. Легенда, размещенная внутри графика, закрывала критически важный участок данных, показывающий аномальный всплеск активности в среду. Клиент заметил это только после презентации, просматривая сырые данные.
После этого случая я разработал свой стандарт визуализаций, где легенда всегда выносится за пределы графика. Этот небольшой прием не только сделал мои визуализации профессиональнее, но и полностью устранил риск "потери" важных инсайтов из-за перекрытий элементами интерфейса.
Ниже приведена таблица, отображающая преимущества выноса легенды в различных сценариях визуализации:
| Сценарий использования | Преимущества выноса легенды | Рекомендуемое расположение |
|---|---|---|
| Графики с большим количеством линий (>5) | Предотвращение загромождения, сохранение читаемости | Справа от графика |
| Временные ряды с длительными периодами | Максимизация горизонтального пространства для данных | Снизу по центру |
| Научные публикации | Соответствие академическим стандартам | Справа или под графиком |
| Дашборды с несколькими графиками | Единообразие, экономия места | В отдельной области дашборда |
| Графики с аннотациями | Устранение визуальных конфликтов с текстовыми элементами | Справа вверху |

Способ 1: Размещение легенды с помощью bbox
Параметр bbox_to_anchor — это настоящий "швейцарский нож" для управления положением легенды в matplotlib. Его гибкость позволяет точно указать, где относительно графика должна располагаться легенда, задав координаты привязки с высокой точностью. 🎯
Принцип работы bbox_to_anchor заключается в указании координат точки привязки для легенды. Эти координаты задаются относительно осей графика в формате кортежа (x, y), где:
x = 0, y = 0— нижний левый угол осей графикаx = 1, y = 1— верхний правый угол осей графика- Значения могут выходить за пределы диапазона [0, 1], что позволяет размещать легенду вне графика
Вот базовый пример размещения легенды справа от графика:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
# Создаем несколько линий для примера
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.plot(x, np.sin(x) * np.cos(x), label='sin(x)cos(x)')
# Размещаем легенду справа от графика
ax.legend(bbox_to_anchor=(1.05, 0.5), loc='center left')
# Добавляем немного пространства справа для легенды
plt.tight_layout()
plt.subplots_adjust(right=0.75)
plt.show()
В этом примере bbox_to_anchor=(1.05, 0.5) размещает точку привязки легенды чуть правее (x=1.05) правой границы графика и вертикально по центру (y=0.5). Параметр loc='center left' указывает, какая точка самой легенды привязывается к заданным координатам — в данном случае, левый центр легенды.
Для тонкой настройки положения легенды можно экспериментировать с различными комбинациями параметров:
| Желаемое положение | bboxtoanchor | loc | Дополнительные настройки |
|---|---|---|---|
| Справа от графика | (1.05, 0.5) | 'center left' | subplots_adjust(right=0.75) |
| Над графиком | (0.5, 1.15) | 'lower center' | subplots_adjust(top=0.85) |
| Под графиком | (0.5, -0.15) | 'upper center' | subplots_adjust(bottom=0.2) |
| В правом верхнем углу (вне) | (1.02, 1.0) | 'upper left' | subplots_adjust(right=0.8) |
| В отдельной строке под графиком | (0.5, -0.35) | 'upper center' | legend(ncol=3), subplots_adjust(bottom=0.3) |
Важно помнить, что после размещения легенды вне графика необходимо также скорректировать компоновку фигуры, используя plt.tight_layout() и/или plt.subplots_adjust(). Это обеспечит достаточно места для легенды и предотвратит её обрезание при сохранении изображения.
Способ 2: Использование параметра loc для изменения положения
Параметр loc — самый простой и интуитивно понятный способ управления положением легенды. Он позволяет указать одно из предопределённых положений без необходимости использования точных координат. Это решение идеально подходит, когда нужно быстро разместить легенду в стандартной позиции. 📍
Основной синтаксис крайне прост:
ax.legend(loc='upper right')
Matplotlib предлагает набор предопределённых строковых значений для параметра loc:
'best'— автоматический выбор оптимального расположения (значение по умолчанию)'upper right','upper left'— верхние углы графика'lower right','lower left'— нижние углы графика'center','center right','center left'— центральные позиции'upper center','lower center'— верхняя и нижняя центральные позиции
Помимо строковых значений, параметр loc также принимает числовые коды от 0 до 10, соответствующие тем же позициям. Например, loc=1 эквивалентно loc='upper right'.
Для вынесения легенды за пределы графика, параметр loc часто используется в сочетании с bbox_to_anchor:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 5, 100)
fig, ax = plt.subplots(figsize=(7, 4))
# Создаем три линии с разными стилями
ax.plot(x, np.exp(-x/2) * np.sin(2*x), 'b-', label='Затухающий синус')
ax.plot(x, x**2/25, 'r--', label='Парабола')
ax.plot(x, 0.5 * np.ones_like(x), 'g:', label='Константа')
# Вариант 1: Легенда снизу, растянутая по ширине
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.15), ncol=3)
plt.tight_layout()
plt.subplots_adjust(bottom=0.25) # Увеличиваем отступ снизу
plt.show()
Михаил Корнеев, научный сотрудник
В процессе подготовки материалов для конференции по физике конденсированных сред я столкнулся с необходимостью представить сравнительный график электропроводности для семи различных образцов. Все кривые имели схожие тренды с небольшими, но критически важными отличиями в области высоких температур.
Первоначально легенда размещалась автоматически внутри графика по принципу 'best', но она закрывала именно ту область, где наблюдались ключевые различия между образцами. Я перепробовал все варианты внутреннего размещения, но каждый раз терял какую-то важную деталь.
Решением стало размещение легенды под графиком в три колонки с помощью комбинации параметров loc='upper center' и bboxtoanchor=(0.5, -0.15). Это позволило не только сохранить видимость всех данных, но и создать более структурированную легенду, где образцы были сгруппированы по типам. Рецензенты отметили высокое качество визуализации, а один из них даже запросил код для создания подобного форматирования.
При размещении легенды вне графика полезно использовать дополнительные параметры:
ncol— определяет количество колонок в легенде (особенно полезно при размещении под/над графиком)frameon— контролирует отображение рамки вокруг легендыfontsize— задает размер шрифтаtitle— добавляет заголовок к легенде
Например, для создания компактной многоколоночной легенды внизу:
ax.legend(
loc='upper center',
bbox_to_anchor=(0.5, -0.15),
ncol=4,
frameon=False,
fontsize=9,
title='Категории'
)
Способ 3: Создание отдельных осей для легенды matplotlib
Создание отдельных осей для легенды — это продвинутый метод, который дает максимальную гибкость в размещении и форматировании легенды. Этот подход позволяет с высокой точностью контролировать положение и размер области легенды относительно всей фигуры. 🎨
Ключевой инструмент в этом методе — функция fig.add_axes(), которая создает новый набор осей с заданными координатами и размерами:
import matplotlib.pyplot as plt
import numpy as np
# Подготовка данных
categories = ['A', 'B', 'C', 'D', 'E']
values1 = [5, 7, 3, 4, 6]
values2 = [2, 4, 8, 5, 3]
# Создание основной фигуры и осей
fig = plt.figure(figsize=(8, 5))
main_ax = fig.add_axes([0\.1, 0.1, 0.7, 0.8]) # [left, bottom, width, height]
# Построение графиков
bars1 = main_ax.bar(categories, values1, width=0.4, align='edge', label='2022')
bars2 = main_ax.bar(categories, values2, width=-0.4, align='edge', label='2023')
main_ax.set_ylabel('Значения')
main_ax.set_title('Сравнительная диаграмма')
# Создание отдельных осей для легенды
legend_ax = fig.add_axes([0\.85, 0.5, 0.1, 0.2]) # Позиция для легенды
legend_ax.axis('off') # Отключаем оси для легенды
# Добавляем легенду на отдельные оси
handles, labels = main_ax.get_legend_handles_labels()
legend = legend_ax.legend(handles, labels, title='Годы', loc='center')
plt.show()
В примере выше:
- Основные оси занимают 70% ширины и 80% высоты фигуры, начиная с позиции [0.1, 0.1].
- Для легенды создаются отдельные оси размером 10% от ширины и 20% от высоты фигуры в позиции [0.85, 0.5].
- Вызов
axis('off')скрывает рамку и координатные оси у области легенды.
Особое преимущество этого метода проявляется при работе с фигурами, содержащими несколько субграфиков. Вы можете создать одну общую легенду для всех субграфиков, разместив её в оптимальном положении:
import matplotlib.pyplot as plt
import numpy as np
# Подготовка данных
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.sin(x) * np.cos(x)
# Создание фигуры с субграфиками
fig = plt.figure(figsize=(10, 6))
# Добавление трёх субграфиков
ax1 = fig.add_subplot(2, 2, 1)
ax1.plot(x, y1, 'r-', label='sin(x)')
ax1.set_title('Синус')
ax2 = fig.add_subplot(2, 2, 2)
ax2.plot(x, y2, 'g-', label='cos(x)')
ax2.set_title('Косинус')
ax3 = fig.add_subplot(2, 2, 3)
ax3.plot(x, y3, 'b-', label='sin(x)cos(x)')
ax3.set_title('Произведение')
# Создание отдельных осей для общей легенды
legend_ax = fig.add_subplot(2, 2, 4)
legend_ax.axis('off')
# Собираем все обработчики и метки из всех субграфиков
handles = []
labels = []
for ax in [ax1, ax2, ax3]:
h, l = ax.get_legend_handles_labels()
handles.extend(h)
labels.extend(l)
# Создаем легенду на отдельных осях
legend_ax.legend(handles, labels, loc='center', title='Функции')
# Настраиваем разметку
plt.tight_layout()
plt.show()
Данный метод особенно полезен в следующих случаях:
| Сценарий | Преимущество метода отдельных осей | Рекомендуемая настройка |
|---|---|---|
| Публикация в научном журнале | Абсолютный контроль над размещением и форматированием | Точное указание размеров в дюймах/процентах |
| Комплексная фигура с несколькими субграфиками | Единая легенда для всех графиков | Размещение в отдельной ячейке сетки |
| Интерактивный дашборд | Возможность создания кликабельной легенды | Добавление обработчиков событий |
| Графики с неравномерной структурой | Точное позиционирование без привязки к графикам | Расчет координат в относительных единицах |
| Легенда со сложным форматированием | Возможность добавления дополнительных элементов | Комбинирование с аннотациями и изображениями |
Способ 4: Размещение легенды через figure.legend()
Метод figure.legend() — это элегантное решение для создания единой легенды на уровне всей фигуры, а не отдельных осей. Этот подход особенно полезен при работе с несколькими субграфиками, когда требуется общая легенда для всех элементов. 🌟
В отличие от ax.legend(), который привязывает легенду к конкретным осям, fig.legend() размещает легенду относительно всей фигуры, что даёт больше свободы в выборе позиции:
import matplotlib.pyplot as plt
import numpy as np
# Создание фигуры
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
# Данные для графиков
x = np.linspace(0, 10, 100)
# Построение графиков на первых осях
line1, = ax1.plot(x, np.sin(x), label='sin(x)')
line2, = ax1.plot(x, np.cos(x), label='cos(x)')
ax1.set_title('Тригонометрические функции')
# Построение графиков на вторых осях
line3, = ax2.plot(x, x**2, label='x²', color='green')
line4, = ax2.plot(x, x**3/100, label='x³/100', color='purple')
ax2.set_title('Степенные функции')
# Создание общей легенды на уровне фигуры
fig.legend(
handles=[line1, line2, line3, line4],
labels=['sin(x)', 'cos(x)', 'x²', 'x³/100'],
loc='lower center',
ncol=4,
bbox_to_anchor=(0.5, 0.0)
)
# Настройка отступов
plt.tight_layout()
plt.subplots_adjust(bottom=0.2) # Оставляем место для легенды снизу
plt.show()
Основные преимущества метода figure.legend():
- Создание единой легенды для нескольких субграфиков
- Возможность объединения элементов из разных осей в одной легенде
- Легкое размещение легенды в любой части фигуры
- Улучшенная читаемость при работе с несколькими графиками
Параметры для тонкой настройки размещения легенды аналогичны тем, что используются с ax.legend():
loc— определяет положение относительно точки привязкиbbox_to_anchor— указывает координаты привязкиncol— задает количество колонокframeon— управляет видимостью рамкиtitle— добавляет заголовок
Для более сложных сценариев можно создавать комбинированные легенды, собирая элементы из разных графиков и даже разных типов визуализаций:
import matplotlib.pyplot as plt
import numpy as np
# Создаем фигуру с разными типами графиков
fig = plt.figure(figsize=(12, 8))
# Добавляем разные типы графиков
ax1 = fig.add_subplot(2, 2, 1) # Линейный график
x = np.linspace(0, 10, 50)
line, = ax1.plot(x, np.sin(x), 'b-', label='Линия')
ax1.set_title('Линейный график')
ax2 = fig.add_subplot(2, 2, 2) # Столбчатая диаграмма
categories = ['A', 'B', 'C', 'D']
values = [3, 7, 2, 5]
bars = ax2.bar(categories, values, color='green', label='Столбцы')
ax2.set_title('Столбчатая диаграмма')
ax3 = fig.add_subplot(2, 2, 3) # Scatter plot
scatter = ax3.scatter(
np.random.rand(20), np.random.rand(20),
c=np.random.rand(20), s=100*np.random.rand(20),
label='Точки'
)
ax3.set_title('Диаграмма рассеяния')
ax4 = fig.add_subplot(2, 2, 4) # Круговая диаграмма
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0)
pie = ax4.pie(
sizes, explode=explode, labels=categories,
autopct='%1.1f%%', shadow=True, startangle=90,
wedgeprops={'label': 'Сегменты'}
)[0]
ax4.set_title('Круговая диаграмма')
# Создаем общую легенду с элементами из разных графиков
fig.legend(
handles=[line, bars[0], scatter, pie[0]],
labels=['Линии', 'Столбцы', 'Точки', 'Сегменты'],
loc='center',
bbox_to_anchor=(0.5, 0.05),
ncol=4
)
# Настраиваем макет
plt.tight_layout()
plt.subplots_adjust(bottom=0.15)
plt.show()
При освоении техник размещения легенды в Python с matplotlib вы открываете для себя новый уровень профессионализма в визуализации данных. Какой бы способ вы ни выбрали — bboxtoanchor для точной настройки, отдельные оси для максимальной гибкости или figure.legend для единой легенды — в вашем арсенале теперь есть инструменты для создания визуализаций публикационного качества. Помните, что грамотно размещенная легенда не только улучшает эстетику вашего графика, но и делает данные более доступными и понятными для аудитории, позволяя избежать потери важной информации из-за перекрытий.