Как вынести легенду за пределы графика в Python: 4 способа

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Разработчики и дата-аналитики, использующие 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], что позволяет размещать легенду вне графика

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

Python
Скопировать код
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 — самый простой и интуитивно понятный способ управления положением легенды. Он позволяет указать одно из предопределённых положений без необходимости использования точных координат. Это решение идеально подходит, когда нужно быстро разместить легенду в стандартной позиции. 📍

Основной синтаксис крайне прост:

Python
Скопировать код
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:

Python
Скопировать код
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 — добавляет заголовок к легенде

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

Python
Скопировать код
ax.legend(
loc='upper center', 
bbox_to_anchor=(0.5, -0.15), 
ncol=4, 
frameon=False, 
fontsize=9, 
title='Категории'
)

Способ 3: Создание отдельных осей для легенды matplotlib

Создание отдельных осей для легенды — это продвинутый метод, который дает максимальную гибкость в размещении и форматировании легенды. Этот подход позволяет с высокой точностью контролировать положение и размер области легенды относительно всей фигуры. 🎨

Ключевой инструмент в этом методе — функция fig.add_axes(), которая создает новый набор осей с заданными координатами и размерами:

Python
Скопировать код
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') скрывает рамку и координатные оси у области легенды.

Особое преимущество этого метода проявляется при работе с фигурами, содержащими несколько субграфиков. Вы можете создать одну общую легенду для всех субграфиков, разместив её в оптимальном положении:

Python
Скопировать код
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() размещает легенду относительно всей фигуры, что даёт больше свободы в выборе позиции:

Python
Скопировать код
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 — добавляет заголовок

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

Python
Скопировать код
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 для единой легенды — в вашем арсенале теперь есть инструменты для создания визуализаций публикационного качества. Помните, что грамотно размещенная легенда не только улучшает эстетику вашего графика, но и делает данные более доступными и понятными для аудитории, позволяя избежать потери важной информации из-за перекрытий.

Загрузка...