Качественная визуализация данных не менее важна для анализа данных, чем методы математической обработки. На сегодняшний день существуют десятки (если не сотни) библиотек для визуализации наборов данных на Python, но иногда в них встречаются уникальные возможности и хотелось бы иметь возможность объединить различные инструменты в единой панели. В статье мы рассмотрим основы библиотеки panel для реализации реактивной модели интерактивных визуализаций и попробуем объединить визуализации из разных библиотек в одном dashboard.
Среди библиотек, которые часто используются для визуализации, можно обозначить следующие:
Altair - декларативное описание визуализации, поддерживает большое количество стандартных диаграмм (bar chart, line chart, scatter plot, …), а также несколько видов интерактивных диаграмм, диаграммы Гантта, …
Bokeh - интерактивные диаграммы на JavaScript. Кроме стандартных диаграмм и гистограмм поддерживаются 3D-поверхности, визуализация графов. Предоставляет возможность приближения и перемещения по линии времени и шкале значений.
HoloViews - конструктор многослойных визуализаций, поддерживает взаимодействие с Bokeh и Matplotlib, предоставляет возможность приближения и перемещения по линии времени и шкале значений.
Matplotlib - универсальный построитель графиков и диаграмм, часто используется для подготовки изображений для научных публикаций. Часто используется совместно с Pandas / Seaborn. Для 3d графики доступна библиотека mplot3d.
Plotly - библиотека для интерактивной 3d-визуализации, основана на библиотеке plotly.js и представляет удобный интерфейс для описания параметров визуализации
Folium - визуализация данных с геопривязкой (была подробно разобрана в этой статье)
Panel предлагает подход к реактивному описанию интерактивной визуализации данных с возможностью интеграции результатов построения различных библиотек в общий dashboard и созданием вспомогательных панелей для управления связанными объектами.
Начнем с установки и подготовим простой проект:
pip install panel
Для ускорения отладки можно запустить проект через panel:
panel serve script.py --show --autoreload
Также можно использовать IPython или Jupyter notebook.
Создадим функцию для исследования изменения температуры и сделаем ее параметризируемой:
import pandas as pd
import numpy as np
from matplotlib.figure import Figure
data = pd.read_csv('https://raw.githubusercontent.com/holoviz/panel/master/examples/assets/occupancy.csv')
data['date'] = data.date.astype('datetime64[ns]')
data = data.set_index('date')
def mpl_plot(avg, highlight):
fig = Figure()
ax = fig.add_subplot()
avg.plot(ax=ax)
if len(highlight):
highlight.plot(style='o', ax=ax)
return fig
def find_outliers(variable='Temperature', window=30, sigma=10, view_fn=mpl_plot):
avg = data[variable].rolling(window=window).mean()
residual = data[variable] - avg
std = residual.rolling(window=window).std()
outliers = (np.abs(residual) > std * sigma)
return view_fn(avg, avg[outliers])
При запуске мы увидим график для соответствующих значений, но что если мы хотели бы исследовать поведение графика при изменении параметров. Передадим функцию find_outliers в виджет interact от panel.
import panel as pn
pn.extension() # Использовать BokehJS, можно подключить расширения latex и др.
pn.interact(find_outliers)
Давайте разберемся как работает interact, это поможет в понимании работы panel в целом. Основным элементом panel является виджет, который может входить в состав группы виджетов (колонки, столбца и др.). Виджет принимает функцию, которая будет создавать график (с использованием одного или нескольких параметров) и обеспечивает встраивание результата функции в финальную страницу и обновление результата при изменении значения аргументов. Дополнительно в pn.interact можно передать определение диапазона значений через kwargs, например, можно ограничить изменение значения sigma и добавить выпадающий список для выбора названия параметра, который будет изображен на графике.
pn.interact(find_outliers, sigma=(10,20), variable=list(data.columns))
Альтернативно можно создать параметризированную панель как класс-расширение от param.Parametrized:
class OccupancyAnalysis(param.Parameterized):
variable = param.Selector(objects=sorted(list(data.columns)))
window = param.Integer(default=10, bounds=(1, 40))
sigma = param.Number(default=10, bounds=(10, 20))
def view(self):
return find_outliers(self.variable, self.window, self.sigma)
Класс представляет два свойства для использования в панелях:
param - виджет с настройкам значений аргументов
view - график (создается функцией view в определении класса)
В случае использования holoviews есть возможность связывания значений, отображаемых на экране с текущими выбранными значениями (например, можно получить значение по линии времени hv.streams.pointerX и определить значение текста зависимым от выбранного X):
class OccupancyAnalysis(param.Parameterized):
variable = param.Selector(objects=sorted(list(data.columns)))
window = param.Integer(default=10, bounds=(1, 40))
sigma = param.Number(default=10, bounds=(10, 20))
def view(self):
return find_outliers(self.variable, self.window, self.sigma)
Виджетом может быть как график (полученный из любой поддерживаемой библиотеки), так и текст (строка, pn.Str или pn.HTML, а также pn.Markdown), таблица (pandas Series), элементы управления (из pn.widgets) и виджеты компоновки (pn.Row - ряд из виджетов, pn.Column - колонка виджетов, pn.Tabs - переключаемые вкладки, pn.GridSpec для определения сеток). Виджеты могут модифицироваться программно (например, в колонку можно добавлять новые виджеты). GridSpec модифицируется как двумерный массив, при этом для объединения ячеек сетки можно использовать слайсы, например 0..2). Для представления любого объекта в виде виджета его можно передать в вызов pn.Pane().
При использовании interact тип элемента управления определяется по типу исходного значения (целое число, число с плавающей точкой, строка, флаг, список), но всегда можно создать панель вручную с использованием виджетов:
pn.widgets.IntSlider - выбор целочисленного значения в диапазоне start - end с шагом step
pn.widgets.FloatSlider - выбор значения с плавающей точкой
pn.widgets.Checkbox / pn.widgets.Toggle - флажок для выбора логического значения
pn.widgets.DataPicker - выбор даты
pn.widgets.DataSlider - выбор даты в диапазоне
pn.widgets.TextInput - ввод текста (также pn.widgets.PasswordInput для скрытия вводимого текста)
pn.widgets.Select - выбор из выпадающего списка
pn.widgets.RadioButtonGroup / pn.widgets.RadioBoxGroup - выбор одного из вариантов в группе
pn.widgets.ColorPicker - выбор цвета
pn.widgets.Button - произвольная кнопка с привязанным действием
pn.widgets.DataFrame - просмотр и редактирование DataFrame
pn.widgets.Progress - индикатор прогресса
При определении параметризированного графика можно использовать следующие типы:
param.Integer - целое число (можно определить диапазон изменения значений bounds)
param.Number - число с плавающей точкой
param.Range - диапазон значений (задается интервалом)
param.String - строковое значение
param.Date - дата (может быть задан диапазон возможных значений в bounds)
param.DataFrame - присоединенный pandas DataFrame
param.Color - цвет
Для наблюдения за параметрами виджетов можно подписаться на значение методом widget.param.watch, которому передается функция-наблюдатель (первым аргументом) и строка с названием наблюдаемого параметра.
Большое количество примеров по использованию библиотеки можно найти на официальном сайте.
В преддверии старта курса "Python для аналитики" приглашаю всех на бесплатный урок в рамках которого будут рассмотрены возможности применения в Python практик использования RFM сегментации клиентов.
Jenkuro
Может кому-то будет полезно: сравнение фреймворков (включая panel)