Создание интерактивных точечных диаграмм с Plotly: обзор Scatter

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

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

  • специалисты в области анализа данных и визуализации
  • студенты и начинающие аналитики, заинтересованные в обучении интерактивной визуализации
  • бизнес-пользователи, заинтересованные в интерпретации и принятии решений на основе данных

    Визуализация данных давно перестала быть просто красивой картинкой в презентациях. Точечные диаграммы Scatter в Plotly — это мощный инструмент интерактивного анализа, позволяющий буквально "общаться" с данными. Когда я впервые создал диаграмму, где пользователь мог навести курсор и увидеть детали каждой точки, увеличить интересующую область и динамически фильтровать данные — я понял, что статичные графики Excel уходят в прошлое. Plotly.Scatter — это не просто функция библиотеки, это новый язык коммуникации с аудиторией через данные. 📊

Хотите овладеть искусством рассказывать истории через данные? Курс «Аналитик данных» с нуля от Skypro погружает вас в мир продвинутой визуализации с нуля. Вы научитесь не только создавать базовые графики, но и разрабатывать интерактивные дашборды с Plotly, которые превратят сухие цифры в наглядные инсайты. Студенты курса делают не просто домашние задания, а решают реальные задачи из индустрии, добавляя в портфолио впечатляющие проекты визуализации.

Основы интерактивных точечных диаграмм в Plotly

Plotly — это одна из наиболее мощных библиотек для создания интерактивных визуализаций в Python, JavaScript, R и других языках. Точечные диаграммы (Scatter plots) представляют собой фундаментальный тип графиков, который позволяет отображать взаимосвязь между двумя числовыми переменными, размещая точки на декартовой системе координат. 🔍

Начнем с базового примера создания точечной диаграммы с использованием Plotly в Python:

Python
Скопировать код
import plotly.express as px
import pandas as pd

# Создание тестовых данных
df = pd.DataFrame({
'x': [1, 2, 3, 4, 5],
'y': [10, 11, 12, 13, 14],
'size': [30, 40, 50, 60, 70],
'category': ['A', 'B', 'A', 'B', 'A']
})

# Создание точечной диаграммы
fig = px.scatter(df, x='x', y='y', size='size', color='category',
title='Базовая интерактивная точечная диаграмма')
fig.show()

Этот простой пример демонстрирует ключевые преимущества Plotly.Scatter перед статическими графиками:

  • Интерактивность — при наведении мыши на точку появляется всплывающая подсказка с данными
  • Масштабирование — пользователи могут приближать интересующие области
  • Экспорт — готовые графики можно скачать в формате PNG
  • Динамическая легенда — кликнув на элемент легенды, можно скрыть или отобразить соответствующие данные

Plotly предлагает два основных подхода к созданию визуализаций:

Plotly Express (px)Plotly Graph Objects (go)
Высокоуровневый APIНизкоуровневый API
Простой синтаксисДетальная настройка
Быстрое создание графиковПолный контроль над визуализацией
Ограниченные возможности кастомизацииРасширенные возможности настройки

Для начинающих рекомендую использовать Plotly Express, который обеспечивает баланс между простотой и функциональностью. Однако для создания сложных визуализаций стоит переходить к Graph Objects:

Python
Скопировать код
import plotly.graph_objects as go

# Создание точечной диаграммы с использованием Graph Objects
fig = go.Figure(
data=go.Scatter(
x=df['x'],
y=df['y'],
mode='markers',
marker=dict(
size=df['size'],
color=['red' if cat == 'A' else 'blue' for cat in df['category']]
),
text=df['category'], # Текст для всплывающих подсказок
hoverinfo='x+y+text' # Формат всплывающей подсказки
)
)

# Настройка макета
fig.update_layout(
title='Точечная диаграмма с использованием Graph Objects',
xaxis_title='X Ось',
yaxis_title='Y Ось'
)

fig.show()

Ключевое преимущество точечных диаграмм Plotly заключается в возможности визуализировать не только две переменные (X и Y), но и добавлять дополнительные измерения через размер точек, их цвет, форму и всплывающие подсказки, что превращает 2D-визуализацию в многомерное представление данных.

Кинга Идем в IT: пошаговый план для смены профессии

Настройка параметров Scatter в Plotly для визуализации

Мощь Plotly.Scatter раскрывается через тонкую настройку параметров, позволяя создавать визуализации, идеально подходящие для конкретных данных и аудитории. Рассмотрим ключевые параметры, которые трансформируют базовую диаграмму в профессиональный аналитический инструмент. ⚙️

Андрей Петров, Lead Data Scientist

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

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

Результат превзошел ожидания — теперь не только я, но и бизнес-пользователи могли буквально "увидеть" сегменты клиентов и принять обоснованные решения. СЕО был настолько впечатлен, что визуализация стала частью ежеквартального отчета для совета директоров.

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

Python
Скопировать код
import plotly.graph_objects as go

fig = go.Figure(go.Scatter(
x=[1, 2, 3, 4, 5],
y=[10, 11, 12, 13, 14],
mode='markers',
marker=dict(
size=15, # размер маркера
color='rgba(255,0,0,0.5)', # цвет с прозрачностью
line=dict(
color='darkred', # цвет обводки
width=2 # толщина обводки
),
symbol='circle', # форма маркера
opacity=0.8, # прозрачность
gradient=dict(
type='radial', # тип градиента
color='lightblue' # цвет градиента
)
)
))

fig.show()

Параметр mode определяет способ отображения данных и может принимать следующие значения:

  • markers — только точки (стандартный scatter plot)
  • lines — только линии, соединяющие точки
  • lines+markers — и точки, и соединяющие линии
  • text — только текстовые метки
  • markers+text — точки с текстовыми метками

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

Python
Скопировать код
import numpy as np

# Генерация случайных данных
np.random.seed(42)
random_x = np.random.randint(1, 100, 100)
random_y = np.random.randint(1, 100, 100)
size = np.random.randint(5, 30, 100)
colors = np.random.randint(0, 10, 100)

fig = go.Figure(go.Scatter(
x=random_x,
y=random_y,
mode='markers',
marker=dict(
size=size,
color=colors,
colorscale='Viridis', # выбор цветовой схемы
showscale=True # показывать цветовую шкалу
),
text=[f'ID: {i}' for i in range(100)], # текст для всплывающих подсказок
hoverinfo='text+x+y' # формат всплывающих подсказок
))

# Настройка макета
fig.update_layout(
title='Расширенная настройка маркеров',
xaxis_title='Ось X',
yaxis_title='Ось Y',
hovermode='closest', # режим всплывающих подсказок
template='plotly_dark' # тема оформления
)

fig.show()
ПараметрОписаниеВозможные значения
symbolФорма маркераcircle, square, diamond, cross, x, triangle, star, etc.
colorscaleЦветовая схемаViridis, Plasma, Inferno, Magma, Cividis, и др.
hovermodeРежим всплывающих подсказокclosest, x, y, x unified, y unified
templateТема оформленияplotly, plotly_white, plotly_dark, ggplot2, seaborn, и др.

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

Python
Скопировать код
fig = go.Figure(go.Scatter(
x=random_x,
y=random_y,
mode='markers',
marker=dict(size=size, color=colors),
customdata=np.column_stack((np.arange(100), np.random.randint(1000, 10000, 100))), # дополнительные данные
hovertemplate='<b>Точка ID:</b> %{customdata[0]}<br>' +
'<b>X:</b> %{x}<br>' +
'<b>Y:</b> %{y}<br>' +
'<b>Значение:</b> %{customdata[1]}<extra></extra>' # настраиваемый формат всплывающей подсказки
))

fig.show()

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

Продвинутые техники работы с Plotly.Scatter

Когда базовые возможности Plotly.Scatter освоены, пора переходить к продвинутым техникам, которые позволяют создавать по-настоящему впечатляющие и информативные визуализации. Именно эти техники отличают работу новичка от профессионала в области визуализации данных. 🚀

Анимация и динамические обновления

Одна из мощных возможностей Plotly — создание анимированных графиков, которые показывают изменение данных во времени:

Python
Скопировать код
import plotly.express as px
import pandas as pd
import numpy as np

# Создание данных
n_frames = 20
n_points = 50
data = []

for frame in range(n_frames):
x = np.random.normal(loc=frame/5, scale=1, size=n_points)
y = np.random.normal(loc=frame/10, scale=1, size=n_points)
size = np.random.randint(5, 15, size=n_points)
category = np.random.choice(['Group A', 'Group B', 'Group C'], size=n_points)

for i in range(n_points):
data.append({
'frame': frame,
'x': x[i],
'y': y[i],
'size': size[i],
'category': category[i]
})

df = pd.DataFrame(data)

# Создание анимированной диаграммы
fig = px.scatter(
df, x='x', y='y', 
animation_frame='frame', 
animation_group='category',
size='size', 
color='category',
range_x=[-5, 10], 
range_y=[-3, 5],
title='Анимированная точечная диаграмма'
)

fig.update_layout(
updatemenus=[{
'type': 'buttons',
'showactive': False,
'buttons': [{
'label': 'Воспроизвести',
'method': 'animate',
'args': [None, {'frame': {'duration': 500, 'redraw': True}, 'fromcurrent': True}]
}]
}]
)

fig.show()

Множественные осевые линии и шкалы

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

Python
Скопировать код
import plotly.graph_objects as go

# Создание данных
x = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50] # Первая переменная
y2 = [500, 400, 300, 200, 100] # Вторая переменная с другим диапазоном

# Создание графика с двумя осями Y
fig = go.Figure()

# Первый набор данных на первой оси Y
fig.add_trace(go.Scatter(
x=x,
y=y1,
name='Метрика 1',
line=dict(color='blue', width=2)
))

# Второй набор данных на второй оси Y
fig.add_trace(go.Scatter(
x=x,
y=y2,
name='Метрика 2',
yaxis='y2', # Привязка к второй оси Y
line=dict(color='red', width=2, dash='dash')
))

# Настройка макета с двумя осями Y
fig.update_layout(
title='График с двумя осями Y',
xaxis_title='Дни',
yaxis=dict(
title='Метрика 1',
titlefont=dict(color='blue'),
tickfont=dict(color='blue')
),
yaxis2=dict(
title='Метрика 2',
titlefont=dict(color='red'),
tickfont=dict(color='red'),
anchor='x',
overlaying='y',
side='right'
),
legend=dict(x=0.02, y=0.95)
)

fig.show()

Марина Соколова, Senior Data Analyst

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

Решение пришло, когда мы применили технику Plotly.Scatter с субграфиками (subplots). Мы создали интерактивную панель из шести связанных графиков, где выбор точки на одном автоматически подсвечивал соответствующие точки на других. Дополнительно мы использовали анимацию, которая показывала динамику изменения поведения пользователей по месяцам.

Эта визуализация позволила нам обнаружить неочевидный паттерн: пользователи, заходившие на сайт в понедельник утром, совершали больше покупок в категории "Электроника", если до этого они просматривали категорию "Гаджеты" в воскресенье вечером. Этот инсайт привел к перестройке рекомендательной системы и увеличению конверсии на 18% для этого сегмента.

Субграфики (Subplots) для сравнительного анализа

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

Python
Скопировать код
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import numpy as np

# Создание сетки субграфиков 2x2
fig = make_subplots(
rows=2, cols=2,
subplot_titles=('Квартал 1', 'Квартал 2', 'Квартал 3', 'Квартал 4'),
shared_xaxes=True,
shared_yaxes=True,
vertical_spacing=0.1
)

# Добавление точечных диаграмм на каждый субграфик
for i, quarter in enumerate([1, 2, 3, 4]):
row = i // 2 + 1
col = i % 2 + 1

# Генерация данных для квартала
np.random.seed(42 * quarter)
x = np.random.normal(loc=quarter, scale=1, size=50)
y = np.random.normal(loc=quarter*2, scale=2, size=50)

# Добавление точечной диаграммы
fig.add_trace(
go.Scatter(
x=x, 
y=y, 
mode='markers',
marker=dict(
color=np.random.randint(0, 255, size=50),
colorscale='Viridis',
showscale=True if i == 0 else False, # Показывать цветовую шкалу только для первого графика
size=10
),
name=f'Q{quarter}'
),
row=row, col=col
)

# Обновление макета
fig.update_layout(
height=800,
title_text='Сравнение данных по кварталам',
showlegend=False
)

fig.show()

Пользовательские взаимодействия и события

Plotly позволяет создавать графики, реагирующие на действия пользователя:

Python
Скопировать код
from dash import Dash, dcc, html, Input, Output
import plotly.express as px
import pandas as pd
import numpy as np

# Создание тестовых данных
np.random.seed(42)
n_points = 100
df = pd.DataFrame({
'x': np.random.normal(0, 1, n_points),
'y': np.random.normal(0, 1, n_points),
'size': np.random.uniform(5, 20, n_points),
'category': np.random.choice(['A', 'B', 'C'], n_points),
'value': np.random.uniform(0, 1, n_points)
})

# Инициализация приложения Dash
app = Dash(__name__)

# Определение структуры приложения
app.layout = html.Div([
html.H1("Интерактивная точечная диаграмма с фильтрацией"),

html.Div([
html.Label("Выберите категорию:"),
dcc.Dropdown(
id='category-filter',
options=[{'label': cat, 'value': cat} for cat in df['category'].unique()],
value=df['category'].unique().tolist(), # По умолчанию выбраны все категории
multi=True
)
], style={'width': '30%', 'margin': '10px'}),

dcc.Graph(id='scatter-plot')
])

# Определение обратной связи для обновления диаграммы
@app.callback(
Output('scatter-plot', 'figure'),
[Input('category-filter', 'value')]
)
def update_graph(selected_categories):
filtered_df = df[df['category'].isin(selected_categories)]

fig = px.scatter(
filtered_df,
x='x',
y='y',
color='category',
size='size',
hover_data=['value'],
title='Фильтрованная точечная диаграмма'
)

return fig

# Запуск приложения
if __name__ == '__main__':
app.run_server(debug=True)

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

Оптимизация точечных диаграмм для веб-приложений

Интеграция интерактивных точечных диаграмм в веб-приложения открывает новые возможности для анализа данных, но также создает дополнительные технические вызовы. Правильная оптимизация Plotly.Scatter для веб-среды критически важна для создания отзывчивых и производительных приложений. 🖥️

Рассмотрим ключевые стратегии оптимизации для различных сценариев использования:

Оптимизация производительности при работе с большими наборами данных

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

Python
Скопировать код
import plotly.graph_objects as go
import numpy as np
from sklearn.cluster import KMeans
import pandas as pd

# Генерация большого набора данных (100,000 точек)
np.random.seed(42)
n_points = 100000
raw_data = pd.DataFrame({
'x': np.random.normal(0, 1, n_points),
'y': np.random.normal(0, 1, n_points),
'category': np.random.choice(['A', 'B', 'C'], n_points)
})

# Метод 1: Прореживание данных (downsampling)
# Выбираем случайную выборку из 5000 точек
sampled_df = raw_data.sample(5000, random_state=42)

# Метод 2: Агрегация через кластеризацию
# Группируем близкие точки, используя K-means
def cluster_points(df, n_clusters=500):
# Применяем KMeans только к числовым столбцам
numeric_data = df[['x', 'y']]
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
df['cluster'] = kmeans.fit_predict(numeric_data)

# Агрегируем данные по кластерам
cluster_centers = kmeans.cluster_centers_

# Подсчитываем количество точек в каждом кластере
cluster_sizes = df.groupby('cluster').size().reset_index(name='count')

# Создаем DataFrame с центрами кластеров и их размерами
clustered_df = pd.DataFrame({
'x': cluster_centers[:, 0],
'y': cluster_centers[:, 1],
'size': cluster_sizes['count'],
# Определяем доминирующую категорию в каждом кластере
'category': [df[df['cluster'] == i]['category'].mode()[0] for i in range(n_clusters)]
})

return clustered_df

clustered_df = cluster_points(raw_data)

# Создаем оптимизированную диаграмму с кластеризованными данными
fig = go.Figure()

for category, color in zip(['A', 'B', 'C'], ['blue', 'red', 'green']):
category_data = clustered_df[clustered_df['category'] == category]

fig.add_trace(go.Scatter(
x=category_data['x'],
y=category_data['y'],
mode='markers',
marker=dict(
size=category_data['size'] / clustered_df['size'].max() * 20 + 5, # Нормализуем размер
color=color,
opacity=0.7,
line=dict(width=1, color='white')
),
name=f'Категория {category}',
hovertemplate='x: %{x:.2f}<br>y: %{y:.2f}<br>Количество точек: %{marker.size}<extra></extra>'
))

fig.update_layout(
title='Оптимизированная точечная диаграмма (кластеризованные данные)',
xaxis_title='X',
yaxis_title='Y',
legend_title='Категории',
hovermode='closest'
)

# Дополнительные оптимизации производительности
fig.update_layout(
uirevision='constant', # Сохраняет состояние UI между обновлениями
autosize=True,
margin=dict(l=20, r=20, t=40, b=20)
)

Сравнение различных методов оптимизации для больших данных:

МетодПреимуществаНедостаткиРекомендуемый размер данных
Без оптимизацииПолная детализация данныхНизкая производительностьДо 5,000 точек
Прореживание (случайная выборка)Простота реализации, сохранение распределенияПотеря редких точек5,000-50,000 точек
Кластеризация (K-means)Сохранение структуры данных, меньше потерь информацииВычислительная сложность предобработки50,000-500,000 точек
Бинирование (гексагональное)Высокая производительность, визуальная структураПотеря индивидуальных точек500,000+ точек
WebGL рендерингАппаратное ускорение графикиОграниченные интерактивные возможностиЛюбой размер

Оптимизация для мобильных устройств

При разработке веб-приложений важно обеспечить корректное отображение на мобильных устройствах:

Python
Скопировать код
fig = go.Figure()

# Добавляем данные
fig.add_trace(go.Scatter(
x=[1, 2, 3, 4, 5],
y=[10, 11, 12, 13, 14],
mode='markers',
marker=dict(size=12, color='blue')
))

# Настройки для адаптивности
fig.update_layout(
# Автоматическая адаптация размера
autosize=True,
# Минимальная высота для мобильных устройств
height=350,
# Уменьшение отступов
margin=dict(l=10, r=10, b=30, t=30, pad=0),
# Настройки легенды для мобильных устройств
legend=dict(
orientation="h", # Горизонтальная легенда
yanchor="bottom",
y=1.02,
xanchor="right",
x=1
)
)

# Оптимизация элементов управления для сенсорных экранов
fig.update_layout(
# Увеличение размера кнопок для сенсорных экранов
updatemenus=[dict(
buttons=[
dict(
label="Сбросить масштаб",
method="relayout",
args=[{"xaxis.range": None, "yaxis.range": None}]
)
],
direction="down",
pad={"r": 10, "t": 10},
showactive=False,
x=0.1,
y=1.15,
xanchor="left",
yanchor="top"
)]
)

# Настройка поведения оси для сенсорного взаимодействия
fig.update_xaxes(
fixedrange=False, # Разрешаем масштабирование по оси X
constrain="domain" # Ограничиваем область для предотвращения выхода за границы
)
fig.update_yaxes(
fixedrange=False, # Разрешаем масштабирование по оси Y
scaleanchor="x", # Сохраняем пропорции при масштабировании
scaleratio=1
)

Асинхронная загрузка и обновление данных

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

Python
Скопировать код
# Пример с использованием Dash для асинхронной загрузки данных
from dash import Dash, dcc, html, Input, Output, callback_context
import plotly.graph_objects as go
import pandas as pd
import time
import random

app = Dash(__name__)

# Имитация получения данных из API
def fetch_data(n_points=100):
# Имитация задержки сетевого запроса
time.sleep(0.5)

# Генерация случайных данных
return pd.DataFrame({
'x': [random.normalvariate(0, 1) for _ in range(n_points)],
'y': [random.normalvariate(0, 1) for _ in range(n_points)],
'size': [random.uniform(5, 20) for _ in range(n_points)],
'timestamp': pd.Timestamp.now()
})

app.layout = html.Div([
html.H1("Асинхронное обновление точечной диаграммы"),

dcc.Loading(
id="loading-1",
type="default", # Тип анимации загрузки
children=html.Div(id="loading-output")
),

dcc.Graph(id="live-scatter-plot"),

dcc.Interval(
id='interval-component',
interval=5*1000, # Обновление каждые 5 секунд
n_intervals=0
),

html.Button('Обновить данные', id='update-button')
])

@app.callback(
Output("live-scatter-plot", "figure"),
Output("loading-output", "children"),
[Input('interval-component', 'n_intervals'),
Input('update-button', 'n_clicks')],
prevent_initial_call=False
)
def update_graph(n_intervals, n_clicks):
# Определяем, что вызвало обратный вызов
ctx = callback_context
trigger = ctx.triggered[0]['prop_id'].split('.')[0] if ctx.triggered else None

# Получаем новые данные
df = fetch_data(n_points=100 if trigger == 'update-button' else 50)

# Создаем фигуру
fig = go.Figure(go.Scatter(
x=df['x'],
y=df['y'],
mode='markers',
marker=dict(
size=df['size'],
color=df['x'],
colorscale='Viridis',
showscale=True
),
hovertemplate='x: %{x:.3f}<br>y: %{y:.3f}<extra></extra>'
))

# Обновляем макет
fig.update_layout(
title=f'Обновлено: {df["timestamp"][0].strftime("%H:%M:%S")}',
xaxis_title='X',
yaxis_title='Y',
autosize=True,
uirevision='constant' # Сохраняет состояние просмотра при обновлениях
)

return fig, f"Данные обновлены в {df['timestamp'][0].strftime('%H:%M:%S')}"

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

Проверьте свои навыки визуализации данных! Пройдите Тест на профориентацию от Skypro, и узнайте, насколько ваши аналитические и технические способности соответствуют требованиям рынка. Этот тест определит не только ваши сильные стороны в работе с данными, но и поможет выбрать оптимальное направление карьерного роста — от аналитика до специалиста по интерактивной визуализации. Результаты дадут конкретные рекомендации по развитию навыков создания профессиональных диаграмм с Plotly!

Кейсы применения Scatter Plotly в аналитике данных

Подлинная ценность Plotly.Scatter раскрывается в контексте реальных аналитических задач. Рассмотрим наиболее эффективные сценарии применения интерактивных точечных диаграмм для решения конкретных бизнес-проблем. 📊

Анализ клиентской базы и сегментация

Визуализация клиентских сегментов помогает бизнесу понять структуру аудитории и адаптировать стратегию под различные группы:

Python
Скопировать код
import plotly.express as px
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

# Предположим, что у нас есть данные о клиентах
df = pd.DataFrame({
'Возраст': [25, 45, 32, 60, 37, 28, 55, 33, 42, 58, 27, 40],
'Доход': [30000, 60000, 45000, 70000, 52000, 35000, 65000, 48000, 56000, 72000, 32000, 50000],
'Частота_покупок': [5, 8, 12, 3, 10, 7, 4, 15, 9, 2, 8, 6],
'Средний_чек': [1500, 3000, 1800, 4500, 2200, 1600, 3800, 1700, 2500, 5000, 1400, 2800],
'Сегмент': ['Молодежь', 'Средний', 'Активный', 'Премиум', 'Средний', 'Молодежь',
'Премиум', 'Активный', 'Средний', 'Премиум', 'Молодежь', 'Средний']
})

# Нормализация данных для PCA
features = ['Возраст', 'Доход', 'Частота_покупок', 'Средний_чек']
scaler = StandardScaler()
scaled_features = scaler.fit_transform(df[features])

# Применение PCA для уменьшения размерности до 2D
pca = PCA(n_components=2)
pca_result = pca.fit_transform(scaled_features)

# Добавление результатов PCA к исходным данным
df['PCA1'] = pca_result[:, 0]
df['PCA2'] = pca_result[:, 1]

# Создание интерактивной точечной диаграммы с сегментацией
fig = px.scatter(
df, x='PCA1', y='PCA2',
color='Сегмент',
size='Средний_чек',
hover_data=features,
title='Сегментация клиентов (PCA)',
labels={
'PCA1': 'Главный компонент 1',
'PCA2': 'Главный компонент 2'
}
)

# Добавление векторов признаков (biplot)
for i, feature in enumerate(features):
fig.add_shape(
type='line',
x0=0, y0=0,
x1=pca.components_[0, i] * 3, # Масштабирование для видимости
y1=pca.components_[1, i] * 3,
line=dict(color='red', width=1, dash='dash'),
)
fig.add_annotation(
x=pca.components_[0, i] * 3.2,
y=pca.components_[1, i] * 3.2,
text=feature,
showarrow=False,
font=dict(color='red')
)

fig.update_layout(
height=700,
legend_title='Сегмент клиента',
)

Анализ корреляций и выявление закономерностей

Точечные диаграммы идеально подходят для анализа взаимосвязей между переменными:

Python
Скопировать код
import plotly.express as px
from sklearn.datasets import load_boston
import pandas as pd
import numpy as np

# Загружаем данные о ценах на жильё в Бостоне
boston = load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)
df['PRICE'] = boston.target

# Вычисляем корреляционную матрицу
correlation_matrix = df.corr()

# Создаём матрицу точечных диаграмм
fig = px.scatter_matrix(
df,
dimensions=df.columns.tolist(),
color='PRICE',
color_continuous_scale=px.colors.sequential.Viridis,
title='Матрица точечных диаграмм для анализа корреляций',
labels={col: col.replace('_', ' ') for col in df.columns},
opacity=0.7
)

# Настройка дополнительных параметров
fig.update_layout(
height=1000,
width=1000,
coloraxis_colorbar=dict(title='Цена'),
autosize=True
)

# Другой вариант: создание интерактивной тепловой карты корреляций
fig_heatmap = px.imshow(
correlation_matrix,
text_auto='.2f',
color_continuous_scale='RdBu_r',
aspect="auto",
title='Тепловая карта корреляций'
)

Мониторинг временных рядов и аномалий

Интерактивные точечные диаграммы эффективны для отслеживания временных данных и выявления аномалий:

Python
Скопировать код
import plotly.graph_objects as go
import pandas as pd
import numpy as np
from sklearn.ensemble import IsolationForest

# Генерация временного ряда с аномалиями
np.random.seed(42)
dates = pd.date_range(start='2024-01-01', periods=100, freq='D')
values = np.sin(np.linspace(0, 10, 100)) * 10 + np.random.normal(0, 1, 100)

# Добавляем искусственные аномалии
anomaly_indices = [10, 35, 65, 80]
for idx in anomaly_indices:
values[idx] += np.random.choice([-15, 15])

# Создаём DataFrame
df = pd.DataFrame({
'date': dates,
'value': values
})

# Обнаружение аномалий с помощью Isolation Forest
model = IsolationForest(contamination=0.05)
df['anomaly'] = model.fit_predict(df[['value']])
df['anomaly'] = df['anomaly'].map({1: 'Normal', -1: 'Anomaly'})

# Создание интерактивной диаграммы для мониторинга
fig = go.Figure()

# Добавляем обычные точки
fig.add_trace(go.Scatter(
x=df[df['anomaly'] == 'Normal']['date'],
y=df[df['anomaly'] == 'Normal']['value'],
mode='lines+markers',
name='Нормальные данные',
marker=dict(color='blue', size=8),
line=dict(color='skyblue', width=2)
))

# Добавляем аномалии
fig.add_trace(go.Scatter(
x=df[df['anomaly'] == 'Anomaly']['date'],
y=df[df['anomaly'] == 'Anomaly']['value'],
mode='markers',
name='Аномалии',
marker=dict(color='red', size=12, symbol='circle-open', line=dict(width=2, color='red'))
))

# Настройка макета
fig.update_layout(
title='Мониторинг временного ряда с обнаружением аномалий',
xaxis_title='Дата',
yaxis_title='Значение',
hovermode='closest',
legend=dict(orientation='h', yanchor='bottom', y=1.02, xanchor='right', x=1)
)

# Добавляем вертикальные линии и аннотации для аномалий
for date, value in zip(
df[df['anomaly'] == 'Anomaly']['date'],
df[df['anomaly'] == 'Anomaly']['value']
):
fig.add_shape(
type='line',
x0=date, y0=min(df['value']) – 2,
x1=date, y1=value,
line=dict(color='red', width=1, dash='dot')
)
fig.add_annotation(
x=date, y=value+2,
text='Аномалия',
showarrow=True,
arrowhead=2,
arrowcolor='red',
arrowsize=1,
arrowwidth=1
)

Геопространственный анализ

Plotly.Scatter может использоваться для создания интерактивных карт с точками интереса:

Python
Скопировать код
import plotly.express as px
import pandas as pd
import numpy as np

# Создаём данные о локациях
np.random.seed(42)
n_stores = 50

df = pd.DataFrame({
'store_id': [f'S{i:03d}' for i in range(1, n_stores+1)],
'lat': np.random.uniform(55.5, 56.0, n_stores), # Широта (Московский регион)
'lon': np.random.uniform(37.4, 38.0, n_stores), # Долгота (Московский регион)
'revenue': np.random.lognormal(mean=12, sigma=1, size=n_stores),
'customers': np.random.randint(500, 5000, n_stores),
'category': np.random.choice(['Продукты', 'Одежда', 'Электроника', 'Рестораны'], n_stores)
})

# Создаём интерактивную карту
fig = px.scatter_mapbox(
df,
lat='lat',
lon='lon',
color='category',
size='revenue',
hover_name='store_id',
hover_data=['customers', 'revenue'],
zoom=9,
mapbox_style='carto-positron', # или 'open-street-map'
title='Распределение магазинов по Москве и окрестностям',
color_discrete_sequence=px.colors.qualitative.Bold
)

# Настройка макета
fig.update_layout(
height=800,
legend_title='Категория магазина',
mapbox=dict(center=dict(lat=55.75, lon=37.6)), # Центр Москвы
margin=dict(l=0, r=0, t=40, b=0)
)

Эти примеры демонстрируют, как Plotly.Scatter может применяться для решения широкого спектра аналитических задач — от сегментации клиентов до обнаружения аномалий и геопространственного анализа. Ключевое преимущество заключается в интерактивности, позволяющей пользователям самостоятельно исследовать данные и находить неочевидные закономерности.

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