Качественная визуализация данных не менее важна для анализа данных, чем методы математической обработки. На сегодняшний день существуют десятки (если не сотни) библиотек для визуализации наборов данных на 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 сегментации клиентов.

Комментарии (1)


  1. Jenkuro
    15.08.2022 16:07
    +1

    Может кому-то будет полезно: сравнение фреймворков (включая panel)