Plotly и интерактивная визуализация

Plotly рисует графики, которые живут в браузере: наведи, приблизь, кликни. Это другой класс задач, чем статичный PNG.

«Интерактив не для красоты. Он позволяет зрителю задавать свои вопросы данным — наводить, фильтровать, приближать».

Matplotlib и Seaborn дают статичную картинку. Plotly даёт интерактивный объект: при наведении всплывает подсказка (hover), колесом мыши можно приблизить, легендой — включать/выключать серии. Это незаменимо для дашбордов, веб-приложений и презентаций, где зритель исследует данные сам.

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

Важно понимать и обратную сторону: интерактив — это не «бесплатное улучшение». Каждый такой график тащит за собой саму библиотеку plotly.js (сотни килобайт JavaScript), требует среды, где этот код исполнится (браузер, Jupyter, веб-страница), и не показывается там, где JS не работает — в PDF, в письме, в распечатке, в README на GitHub. Поэтому выбор «Plotly или Matplotlib» — это в первую очередь вопрос канала доставки: где и как ваш график будет жить.

import plotly.express as px

# Plotly Express — высокоуровневый API, как seaborn
fig = px.scatter(df, x="area", y="price",
                 color="district", size="rooms",
                 hover_data=["address"])
fig.show()

# graph_objects — низкоуровневый, полный контроль
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(x=days, y=users, mode="lines+markers"))
fig.update_layout(title="Активные пользователи")
fig.show()

Два API как два этажа: Plotly Express (px) — высокоуровневый, одна строка из DataFrame (аналог Seaborn). graph_objects (go) — конструктор из «трейсов» для полного контроля и сложных композиций.

Как работает под капотом

Plotly строит не картинку, а JSON-описание графика (данные + layout), которое рендерит JavaScript-библиотека plotly.js в браузере как SVG/WebGL. Поэтому график «живой»: браузер пересчитывает отображение при зуме и наведении. Px под капотом собирает этот же JSON из «трейсов» go — то есть px это удобная обёртка над go, как pyplot над Axes.

Hover-подсказка показывает значения точки. Подготовим такие подписи вручную — это содержимое будущего tooltip.

# Готовим hover-подписи для точек (то, что всплывёт при наведении)
points = [
    {"city": "Москва", "area": 54, "price": 12.5},
    {"city": "Казань", "area": 48, "price": 6.2},
    {"city": "Сочи",   "area": 60, "price": 14.0},
]

for p in points:
    per_m2 = p["price"] * 1000 / p["area"]   # тыс. руб за м2
    hover = "{}: {} м2, {} млн ({:.0f} тыс/м2)".format(
        p["city"], p["area"], p["price"], per_m2)
    print(hover)

«Попробуй сам ▶» — строки, которые вы собрали, и есть то, что Plotly показывает в hover при наведении на точку.

Частые ошибки

Использовать интерактив там, где он не нужен (статичный отчёт в PDF) — лишний вес и зависимость от JS. Перегружать hover десятком полей. Путать px и go и пытаться смешивать несовместимо. Забывать, что Plotly-график не отрендерится в обычном PNG-пайплайне без kaleido.

Ещё несколько частых промахов. Строить scatter с десятками тысяч точек обычным go.Scatter и удивляться, что страница подвисает: для больших объёмов есть go.Scattergl (рендеринг на WebGL вместо SVG), который держит сотни тысяч точек. Дальше — забывать, что в скрипте вне ноутбука fig.show() открывает график во временной HTML-вкладке браузера, а не рисует в консоли; чтобы сохранить результат, нужен fig.write_html() для интерактивной версии или fig.write_image() (требует kaleido) для статичной.

И типичная ошибка восприятия API: думать, что px и go — конкурирующие библиотеки, между которыми надо выбрать раз и навсегда. На деле они дополняют друг друга — можно начать с px.scatter, а потом дослать на ту же фигуру fig.add_trace(go.Scatter(...)) или поправить оформление через fig.update_traces и fig.update_layout. Объект fig у обоих один и тот же, поэтому смешивать их не только можно, но и нормально.

Best practices

  • Интерактив — для дашбордов и веба; для печати/PDF берите Matplotlib.
  • Начинайте с Plotly Express; переходите на go только при нехватке контроля.
  • Держите hover лаконичным: 2–4 ключевых поля.
  • Для экспорта в статичный PNG ставьте kaleido.

Итог: Plotly открывает интерактив. Дальше соберём из таких графиков дашборд.

Проверьте себя
1. Чем Plotly принципиально отличается от Matplotlib?
AОн быстрее считает среднее
BОн строит интерактивные графики, рендерящиеся в браузере (hover, zoom)
CОн не умеет scatter
DОн работает только в PDF
2. Как соотносятся Plotly Express (px) и graph_objects (go)?
AЭто несовместимые библиотеки
Bpx — высокоуровневая обёртка, собирающая те же трейсы go
Cgo проще px
Dpx рендерит в PDF, go в браузере