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

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

Самыми распространенными библиотеками для создания визуализаций на Python являются Matplotlib и Seaborn, но существует и множество других инструментов.

В этом руководстве мы изучим инструменты HoloViz, а точнее Panel и hvPlot  —  библиотеки с открытым исходным кодом, которые используются для создания интерактивных диаграмм и контрольных панелей. Также узнаем, как легко развернуть и поделиться контрольной панелью с помощью Jupyter Notebook.

В этом проекте мы будем использовать данные о различных покемонах, доступные на Kaggle и Wikipedia, а также данные о продажах игр про покемонов.

Краткий обзор

Мы выполним следующие задачи.

  • Создадим простой интерактивный график, используя hvPlot и Pandas.
  • Построим более сложные визуализации, используя Panel для создания виджетов, которые будут фильтровать данные, и hvPlot для отображения этих данных.
  • Создадим контрольную панель, показывающую табличные данные, информацию о проекте, а также различные интерактивные диаграммы.
  • Узнаем, как развертывать контрольную панель на Heroku, чтобы проектом можно было делиться.

На GitHub можно найти полную версию кода и изучить окончательный вариант контрольной панели, а на Heroku  —  взаимодействовать с визуализациями.

Быстрая визуализация с помощью Pandas и hvPlot

В Pandas графики создаются с помощью pandas.DataFrame.plot, использующего по умолчанию бэкенд Matplotlib.

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

sales.plot(kind='line', x='Year', y='Units sold(in millions)', 
color='orange', grid=True,
title='Pokémon Game Sales');

После установки hvPlot появляется возможность создавать интерактивные графики pandas путем изменения предустановленного бэкенда: pd.options.plotting.backend = 'holoviews'.

Затем, применив тот же код, получаем:

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

Более того, используя логику hvPlot, можно создавать и совмещать разные графики, добавляя * между ними. Также можно внести неотображаемую информацию с помощью аргумента hover_cols:

sales.plot(kind='line', x='Year', y='Units sold(in millions)', 
color='orange', grid=True, title='Pokémon Game Sales', hover=False) \
* sales.plot(kind='scatter', x='Year', y='Units sold(in millions)',
color='#c70000', hover_cols='Game')

Мы создали на нескольких строках кода интерактивную визуализацию, используя только pandas и hvPlot!

Конвейер данных и виджеты 

Теперь посмотрим, как добавить Panel для создания более сложных диаграмм.

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

Отфильтруем данные с помощью виджета Select, а затем, чтобы синхронизировать их с текущим выбором type, создадим конвейер данных:

# Создание селектора (виджета), содержащего все существующие типы покемонов
pok_types = list(df.type_1.unique())
pok_type = pn.widgets.Select(name='Type', options=pok_types)

# Создание интерактивного датафрейма
idf = df.interacive()

# Реализация взаимодействия с данными
data_pipeline = (
idf[
(idf.type_1 == pok_type) | (idf.type_2 == pok_type)
]
)

Получаем следующий селектор:

Теперь, используя data_pipeline в качестве данных для создания новых графиков, появится возможность фильтрации этих графиков по определенному типу покемона.

К примеру, можно создать столбчатый график, показывающий слабости конкретного типа покемона:

#  Выбор данных, содержащих средний показатель слабости, и переименование значений в получаемый урон
data_damage = data_pipeline.iloc[:, -18:].mean().rename('Damage')

# Создание столбчатого графика
data_damage.hvplot(kind='bar',
title='This type is Weak against...',
rot=45,
c='Damage', colorbar=True,
colormap='RdYlGn_r',
shared_axes=False,)

Итак, мы создали столбчатый график, показывающий средний получаемый урон от определенного типа атаки. Также с помощью виджета можно выбрать любой тип покемона и посмотреть его слабости.

Как видите, мы можем использовать палитру Matplotlib, а также выбрать конкретный столбец для применения градиента цвета. Например, выбрав применение градиента на “повреждениях”, мы можем четко увидеть красным цветом типы атак, к которым выбранный вид покемона наиболее уязвим.

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

data_pipeline.hvplot(x='weight_kg', y='height_m', 
by='type_2',
kind='scatter',
hover_cols=['name', 'type_1', 'type_2'],
title='Relationship between Weight (kg) and Height (m), by Type',
width=700, height=500,
grid=True,
)

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

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

# Для создания табличного графика
data_pipeline[['pokedex_number', 'name', 'total_points']].hvplot(kind='table',
title='Pokémons',
width=600, height=400)

Создание контрольной панели 

Пришло время создать контрольную панель, объединив разные типы диаграмм.

Для этого используем шаблоны Panel. Существуют различные готовые варианты, которые можно настраивать, но также можно создавать свои.

Независимо от выбора, все эти шаблоны позволяют легко разграничить четыре основные области страницы:

  • заголовок;
  • боковое поле;
  • основная область;
  • всплывающее окно.

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

Внутрь строк и столбцов добавляем предыдущие графики. Здесь будем использовать FastListTemplate, а в качестве темы по умолчанию укажем DarkTheme. Затем добавим заголовок, боковое поле с текстом и изображением, главный участок с графиками и в конце зададим параметры для настройки цветов.

template = pn.template.FastListTemplate(theme=DarkTheme,
title = 'Pokémon Interactive Dashboard',
sidebar=[
pn.pane.Markdown('# О проекте'),
pn.pane.Markdown('#### Этот проект использует данные, доступные на [Kaggle] https://www.kaggle.com/datasets/mariotormo/complete-pokemon-dataset-updated-090420) и на [Wikipedia](https://en.wikipedia.org/wiki/Pok%C3%A9mon_(video_game_series)# Справка о покемонах для изучения различных видов визуализаций с использованием инструментов HoloViz: [Panel](https://panel.holoviz.org/) [hvPlot](https://hvplot.holoviz.org/)'),
pn.pane.JPG('thimo-pedersen-dip9IIwUK6w-unsplash.jpg', sizing_mode='scale_both'),
pn.pane.Markdown('[Photo by Thimo Pedersen on Unsplash](https://unsplash.com/photos/dip9IIwUK6w)'),
pn.pane.Markdown('## Фильтрация по типу'),
pok_type
],
main=[pn.Row(
pn.Column(viz0.panel(width=600, height=400, margin=(0,20))),
pn.Column(pn.Row(viz1.panel(width=700, height=250, margin=(0,20))),
pn.Column(viz2.panel(width=700, height=250), margin=(0,20))),
),
pn.Row(salesplot.opts(width=1400, height=200))
],
accent_base_color='#d78929',
header_background='#d78929',
sidebar_footer='<br><br><a href="https://github.com/pcmaldonado/PokemonDashboard">GitHub Repository</a>',
main_max_width='100%'
)

template.servable();

Метод .servable() предоставляет контрольную панель, чтобы ее можно было развернуть. Однако ее также можно увидеть локально в другом окне, используя .show().

Окончательный результат выглядит так:

Развертывание контрольной панели на Heroku 

Большая часть работы уже позади!

Для тех, кто хочет поделиться будущими проектами, Panel предлагает руководство по развертыванию серверов, в котором показано, как производить развертывание на Heroku. Данная услуга на этой платформе бесплатна.

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

  • Блокнот Jupyter, содержащий информационную панель или диаграммы (с использованием .servable() для объекта развертывания), а также базовые данные.
  • Файл Procfile, указывающий Heroku перечень команд для выполнения.
  • Файл requirements.txt, содержащий используемые библиотеки, а также инструмент nbconvert для конвертации кода Jupyter Notebook.
  • Файл runtitme.txt, содержащий используемую версию Python.

Вот и все. 

Заключение

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

В этой статье мы рассмотрели методы создания интерактивных диаграмм и контрольных панелей с помощью инструментов HoloViz, а именно:

  • использование hvPlot в качестве бэкенда для графиков pandas;
  • создание виджета и конвейера данных для фильтрации и дальнейшего взаимодействия с диаграммами;
  • создание контрольной панели, объединяющей графики, а также добавление полезной информации в нее;
  • развертывание контрольной панели на Hеroku.

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

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи Paula Maldonado: Guide to creating interactive visualizations using Python

Предыдущая статьяОсновы аутентификации для начинающих
Следующая статьяКак улучшить код на TypeScript: 5 рекомендаций