Matplotlib: Как построить график с двумя осями Y?

При создании визуализаций данных нередко возникает необходимость отобразить на одном графике две серии данных, имеющих совершенно разные диапазоны значений или даже разные единицы измерения. Стандартный график с одной осью Y в таком случае может быть неэффективен: одна из серий будет «сплющена» из-за масштаба другой, или же оси будут иметь неинформативные подписи.

Зачем использовать две оси Y?

Использование двух независимых осей Y на одном графике позволяет отображать и сравнивать тренды двух наборов данных одновременно, даже если их абсолютные значения сильно различаются. Левая ось Y обычно ассоциируется с первой серией данных, а правая — со второй. Это делает график более компактным и позволяет быстрее выявлять взаимосвязи или расхождения в динамике.

Основные случаи применения графиков с двумя осями

Две оси Y полезны в множестве сценариев анализа данных, в частности:

  • Экономика и финансы: Отображение курса валюты и объема торгов; прибыли и рентабельности.
  • Метеорология: Совмещение графиков температуры и уровня осадков.
  • Маркетинг и веб-аналитика: Сравнение количества посетителей сайта и коэффициента конверсии; показов рекламы и CTR.
  • Технические измерения: Построение графиков напряжения и тока.
  • Медицина: Анализ динамики давления и пульса.

Во всех этих случаях данные имеют разную природу и масштабы, что делает двойную ось Y удобным инструментом визуализации.

Создание графика с двумя осями Y: базовый подход

В библиотеке Matplotlib создание графика с двумя осями Y реализуется с помощью метода twinx(), доступного для объектов Axes.

Использование plt.twinx() для создания второй оси

Метод twinx() создает новый объект Axes, который «близнец» существующего объекта Axes в том смысле, что они используют общую ось X. Новый объект Axes располагается поверх старого и имеет свою собственную ось Y справа. Важно понимать, что вы работаете с двумя разными объектами Axes, к каждому из которых можно применять свои методы построения и настройки.

Настройка цветов и меток для каждой оси

Для улучшения читаемости графика крайне важно четко различать, какая линия (или столбец) соответствует какой оси Y. Это достигается путем:

  • Присвоения каждой серии данных и соответствующей оси Y уникального цвета.
  • Добавления информативных меток к обеим осям Y.
  • Использования легенды, явно указывающей на связь между цветом линии и осью.

Пример кода: простой график с двумя осями

Рассмотрим пример из области веб-аналитики: отображение ежедневного числа посещений сайта и коэффициента конверсии за неделю.

import matplotlib.pyplot as plt
import numpy as np
from typing import List

def plot_dual_y_axis(days: List[str], visits: List[int], conversion_rate: List[float]):
    """
    Строит график с двумя осями Y: количество посещений и коэффициент конверсии.

    Args:
        days: Список дней недели.
        visits: Список ежедневных посещений сайта.
        conversion_rate: Список ежедневных коэффициентов конверсии (в %).ъ
    """
    fig, ax1 = plt.subplots(figsize=(10, 6))

    # Настройка первой оси Y (Посещения)
    color_visits = 'tab:blue'
    ax1.set_xlabel('День недели')
    ax1.set_ylabel('Посещения', color=color_visits)  # Метка оси Y1
    line_visits, = ax1.plot(days, visits, color=color_visits, marker='o', label='Посещения') # Построение данных 1
    ax1.tick_params(axis='y', labelcolor=color_visits)
    ax1.grid(True, axis='y', linestyle='--', alpha=0.6)

    # Создание второй оси Y, использующей ту же ось X
    ax2 = ax1.twinx()

    # Настройка второй оси Y (Коэффициент конверсии)
    color_conversion = 'tab:red'
    ax2.set_ylabel('Коэффициент конверсии (%)', color=color_conversion) # Метка оси Y2
    line_conversion, = ax2.plot(days, conversion_rate, color=color_conversion, marker='x', label='Коэффициент конверсии') # Построение данных 2
    ax2.tick_params(axis='y', labelcolor=color_conversion)

    # Добавление заголовка и легенды
    plt.title('Посещения сайта и Коэффициент конверсии за неделю')

    # Объединение легенд
    lines = [line_visits, line_conversion]
    ax1.legend(lines, [line.get_label() for line in lines], loc='upper left')

    plt.tight_layout() # Автоматическая корректировка размещения элементов
    plt.show()

# Пример данных
weekdays: List[str] = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс']
daily_visits: List[int] = [1200, 1500, 1300, 1600, 1800, 2500, 2200]
daily_conversion_rate: List[float] = [2.5, 2.8, 2.4, 3.0, 3.5, 4.0, 3.8]

# Вызов функции для построения графика
plot_dual_y_axis(weekdays, daily_visits, daily_conversion_rate)

В этом коде мы сначала создаем стандартный объект Axes (ax1), строим на нем данные по посещениям и настраиваем его левую ось Y. Затем с помощью ax2 = ax1.twinx() создаем вторую ось ax2, связанную с ax1 по X. На ax2 строим данные по коэффициенту конверсии и настраиваем правую ось Y. Для легенды собираем объекты линий с обеих осей и создаем общую легенду на ax1.

Продвинутая настройка графиков с двумя осями

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

Реклама

Размещение легенды для обоих наборов данных

Как показано в примере выше, стандартный метод ax.legend() для одного объекта Axes не включает линии с другого. Необходимо вручную собрать объекты Line2D с обеих осей и передать их вместе с соответствующими метками в один вызов ax.legend() или fig.legend().

# ... (код до построения линий)

# Вместо ax1.legend(...) и ax2.legend(...):

# Собираем хэндлы (объекты линий) и метки с обеих осей
handles1, labels1 = ax1.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
handles = handles1 + handles2
labels = labels1 + labels2

# Размещаем общую легенду на одной из осей или на фигуре
ax1.legend(handles, labels, loc='upper left')
# Или fig.legend(handles, labels, loc='upper right')

# ... (остальной код)

Синхронизация масштабов осей Y

В большинстве случаев при использовании twinx() оси Y имеют независимые масштабы, что и является целью. Однако, если данные на разных осях как-то связаны пропорционально, может потребоваться ручная установка пределов осей (ax.set_ylim()) для поддержания этой связи или визуальной сопоставимости в определенных диапазонах. Matplotlib не делает этого автоматически.

Использование различных типов графиков (линейные графики, столбчатые диаграммы) на разных осях

На разных осях можно строить графики различных типов. Например, столбчатую диаграмму для одного набора данных (например, объем продаж) на одной оси и линейный график для другого набора (например, маржа) на другой оси. Для этого достаточно вызвать соответствующие методы построения (ax.bar(), ax.plot()) для нужного объекта Axes (ax1 или ax2).

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

Графики с двумя осями Y могут быть очень информативными, но их неправильное использование может привести к путанице или искажению восприятия данных.

Перекрытие элементов графика: как избежать

Поскольку две оси Y располагаются на одной области построения, элементы графика (линии, метки данных) могут перекрываться. Способы избежать этого включают:

  • Использование разных типов маркеров и стилей линий.
  • Настройка прозрачности (alpha) для элементов.
  • Сдвиг текстовых меток.
  • Осторожное использование сетки: возможно, стоит оставить сетку только для одной оси или использовать пунктирные линии разного стиля/цвета для каждой оси.

Несоответствие масштабов данных: методы нормализации

Хотя две оси Y и предназначены для данных разного масштаба, иногда требуется сравнить их относительное изменение. В таких случаях может быть полезно построить не сами данные, а их нормализованные значения (например, в процентах от максимального или начального значения), используя одну ось Y. Выбор между нормализацией и двумя осями Y зависит от цели визуализации: показать абсолютные значения и их индивидуальные тренды (две оси) или показать относительные изменения по отношению друг к другу (нормализация на одной оси).

Визуальная перегрузка: советы по упрощению восприятия

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

  • Используйте контрастные, но не раздражающие цвета.
  • Избегайте избыточных декоративных элементов.
  • Убедитесь, что метки осей и легенда четко указывают, какие данные к какой оси относятся (используйте совпадающие цвета текста меток и линий).
  • Если возможно, сократите количество отображаемых данных или используйте агрегированные значения, если детализация не критична.

Заключение

Графики с двумя осями Y являются мощным инструментом в арсенале визуализации данных Matplotlib, позволяющим эффективно сравнивать тренды двух наборов данных с различными масштабами или единицами измерения.

Преимущества и недостатки графиков с двумя осями Y

  • Преимущества: Компактное сравнение разнородных данных, выявление корреляций.
  • Недостатки: Могут быть сложны для интерпретации новичками; требуют внимательной настройки для избежания визуальной путаницы; могут быть использованы для визуального искажения связи между данными, если оси выбраны некорректно.

Рекомендации по эффективному использованию

Используйте две оси Y осознанно. Четко обозначьте каждую ось и связанные с ней данные (цвет, метки, легенда). Убедитесь, что график не выглядит перегруженным. Всегда задавайтесь вопросом, действительно ли две оси улучшают понимание данных, или же разделение на два отдельных графика или нормализация были бы более удачным решением.


Добавить комментарий