Plotly для аналитика: интерактивные графики

Plotly vs matplotlib/seaborn

Matplotlib — стандарт научной визуализации в Python. Seaborn — удобная обёртка для статистических графиков. Оба рендерят статические изображения: вы получаете PNG или SVG, который показывает данные, но не позволяет взаимодействовать.

Plotly — другой подход. Он создаёт интерактивные графики на JavaScript. Пользователь может навести курсор и увидеть точные значения, выделить область для зума, скрыть серии кликом по легенде. Для дашбордов и презентаций это меняет качество донесения информации.

Для аналитика Plotly полезен в нескольких сценариях: интерактивные дашборды в Streamlit и Dash, графики в Jupyter с live zoom, HTML-отчёты, которые можно прислать стейкхолдеру, графики для blog-постов в TG или LinkedIn.

Установка

pip install plotly

Обычно вместе ставят pandas и numpy для удобства.

Базовый пример

Plotly Express — высокоуровневый API, похожий на seaborn:

import plotly.express as px
import pandas as pd

df = pd.read_csv('sales.csv')

fig = px.line(
    df,
    x='date',
    y='revenue',
    color='region',
    title='Revenue by region'
)
fig.show()

В Jupyter сразу откроется интерактивный график. В скрипте — браузер с рендером.

Plotly Express покрывает типовые графики: line, bar, scatter, histogram, box plot, heatmap, pie, treemap, sunburst. Для 80% задач хватает.

Интерактивность из коробки

То, что делает Plotly ценным — это встроенные фичи интерактива:

Hover. Навели курсор — увидели точное значение. Настраивается через hover_data:

fig = px.scatter(
    df, x='price', y='quantity',
    hover_data=['product_name', 'category']
)

Zoom и pan. Выделили область мышью — график приблизился. Можно крутить pan'ом. Reset — двойной клик.

Toggle legend. Кликнул на серию в легенде — скрыл/показал. Удобно для графиков с 5+ линиями.

Export. Встроенная кнопка для скачивания PNG.

Всё это работает без дополнительного кода. Просто используете Plotly — получаете интерактивность.

Кастомизация через update_layout

Для доводки графика до production-качества — update_layout:

fig = px.line(df, x='date', y='revenue')
fig.update_layout(
    title='Weekly Revenue 2026',
    xaxis_title='Week',
    yaxis_title='Revenue (RUB)',
    template='plotly_white',
    height=500,
    legend=dict(orientation='h', yanchor='bottom', y=1.02),
    hovermode='x unified'
)

hovermode='x unified' — особенно полезная опция. При наведении показывает значения всех серий в одной точке. Идеально для сравнения.

Несколько серий

Plotly легко работает с группировкой:

df = pd.DataFrame({
    'date': pd.date_range('2026-01-01', periods=30),
    'metric': ['DAU'] * 10 + ['Revenue'] * 10 + ['Orders'] * 10,
    'value': ...
})

fig = px.line(df, x='date', y='value', color='metric')

Каждая уникальная категория в color превращается в отдельную линию. Автоматическая легенда, цвета, interactivity.

Dual-axis графики

Частая задача — показать две метрики с разными единицами (DAU и revenue). Нужен dual axis:

from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(specs=[[{'secondary_y': True}]])

fig.add_trace(
    go.Scatter(x=df['date'], y=df['dau'], name='DAU'),
    secondary_y=False
)

fig.add_trace(
    go.Scatter(x=df['date'], y=df['revenue'], name='Revenue'),
    secondary_y=True
)

fig.update_yaxes(title='DAU', secondary_y=False)
fig.update_yaxes(title='Revenue (RUB)', secondary_y=True)
fig.show()

Для dual axis нужен более низкоуровневый API (graph_objects), Express не поддерживает. Но результат стоит усилий.

Heatmap для когортных таблиц

Классическое применение — retention cohort heatmap:

import plotly.express as px

fig = px.imshow(
    retention_matrix,  # pandas DataFrame с когортами в строках, неделями в столбцах
    aspect='auto',
    color_continuous_scale='YlGnBu',
    labels=dict(x='Weeks since signup', y='Cohort', color='Retention %')
)
fig.update_layout(title='Retention Cohort Matrix')

В отличие от seaborn, здесь можно hover на каждой ячейке и увидеть точное значение. Для презентаций эффектно.

Интерактивный scatter с фасетами

Для сравнения по сегментам:

fig = px.scatter(
    df,
    x='ctr', y='conversion_rate',
    color='channel',
    size='visits',
    facet_col='device',  # разбивка по устройствам
    hover_data=['campaign_name']
)

Получается grid графиков (mobile, desktop, tablet) в одной фигуре. Каждый — scatter с размером точки = число визитов.

Мощный инструмент для exploratory analysis в презентации.

Combined charts

Часто нужен комбинированный chart: бары + линия на одной оси.

import plotly.graph_objects as go

fig = go.Figure()

fig.add_trace(go.Bar(
    x=df['month'], y=df['revenue'],
    name='Revenue', marker_color='lightblue'
))

fig.add_trace(go.Scatter(
    x=df['month'], y=df['orders'],
    name='Orders', yaxis='y2',
    line=dict(color='darkred', width=3)
))

fig.update_layout(
    yaxis=dict(title='Revenue'),
    yaxis2=dict(title='Orders', overlaying='y', side='right')
)

Популярный паттерн для ежемесячных отчётов: revenue барами + orders линией.

Владение инструментами визуализации — часть работы аналитика, особенно на presentation-стороне. В тренажёре Карьерник есть задачи на Python и визуализацию с разбором best practices.

Экспорт в HTML

Одна из killer-фич Plotly — экспорт в standalone HTML:

fig.write_html('report.html')

Это одиночный файл с полным графиком. Можно отправить по email или открыть без интернета. Все интерактивные фичи работают.

Для статических сценариев (PDF-отчёты, PowerPoint):

fig.write_image('chart.png', width=1200, height=600, scale=2)

Нужен kaleido package.

Стили и темы

Plotly имеет встроенные темы через template:

fig.update_layout(template='plotly_white')
# Другие: 'plotly_dark', 'ggplot2', 'seaborn', 'simple_white'

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

import plotly.io as pio

pio.templates['my_company'] = go.layout.Template(
    layout=dict(
        colorway=['#C15F3C', '#3C9DC1', '#7AC13C'],
        font=dict(family='Arial'),
        paper_bgcolor='#F5F5F5'
    )
)

pio.templates.default = 'my_company'

Теперь все графики автоматически в вашем фирменном стиле.

Интеграция со Streamlit и Jupyter

Jupyter: работает из коробки после pip install plotly. Графики рендерятся inline.

Streamlit: st.plotly_chart(fig).

Dash: нативная интеграция, Dash построен на Plotly.

Jupyter widgets: можно обновлять график в ответ на sliders/dropdowns через fig.update_traces.

Ограничения

Plotly медленнее matplotlib для большого количества точек. 100k точек в scatter — ок. 1M — начинаются тормоза. Для больших данных можно использовать datashader или семплировать.

HTML-файлы с Plotly-графиками большие (несколько MB на график). Не идеально для email.

Кривая обучения у graph_objects API крутая. Plotly Express покрывает типовые случаи, но нестандартные графики требуют разобраться в layout, traces, annotations.

Альтернативы

Bokeh — аналогичный подход, тоже interactive через JavaScript. Популярен в научном сообществе.

Altair — декларативный синтаксис на основе Vega-Lite. Очень выразительно, но ограничен в complex сценариях.

Echarts-python — обёртка над Apache ECharts. Красивые китайские библиотеки, но менее популярна в западном сообществе.

Для аналитика Plotly — лучший баланс между простотой и возможностями.

Читайте также

FAQ

Plotly vs Tableau?

Plotly — для кода, Python. Tableau — drag-n-drop, BI-инструмент. Разные категории. Plotly хорош для custom дашбордов и интеграции в Python-приложения.

Бесплатный?

Open-source MIT license. Plotly Dash Enterprise — платный для управляемого хостинга, но для большинства задач хватает бесплатной версии.

Работает ли без интернета?

Да. Все рендеринги клиентские, JavaScript-библиотека встраивается в HTML.

Python или Plotly.js?

Для аналитика — Python. Plotly.js (JavaScript) — для фронтенд-разработчиков.