python

О прелестях перехода на панель и не только

  • пятница, 11 октября 2019 г. в 00:29:27
https://habr.com/ru/post/470864/
  • Python
  • Визуализация данных
  • Инфографика


image

Как очевидно из заголовка, речь пойдет о библиотеке Panel, которая позволяет конвертировать Jupyter блокноты в безопасные веб приложения, где начинка скрыта от нетехнических пользователей, но остается свобода манипулирования внутренними параметрами, то есть не просто перестраивать данные, но и делать запросы в кернел. TL;DR Shiny for Python.

Одна из главных проблем бизнес аналитики состоит в том, что какой бы классной она ни была,
она часто не доходит до пользователя, принимающего на ее основе решения. IBM CTO of AI and data science говорит что только 13% проектов в области науки о данных доходят до продакшена и одна из главных причин — затрудненное сотрудничество всех участвующих в проектах. Сократив разрыв между датасатанистом, программистом деплоящим проект и аналитиком предметной области можно существенно повысить общий выхлоп, сократить сроки и сделать конечный продукт более продуманным.

Именно эту проблему решают несколько имеющихся сейчас в данной нише продуктов.
Для хорошего, маштабируемого деплоя есть Dash. В моем прошлом посте я делал небольшую
иллюстрацию на примере анализа рынка подержанных машин. За достоинства Даша нужно платить цену в виде того, что это отдельный апп который надо отдельно писать, из графики поддерживается Plotly, нужно дизайнить интерфейс, подкрутить немного CSS/HTML и при обновлении модели анализа если она в блокнотах — нужно поддерживать два кода, в целом не очень удобно пока проект в стадии развития.

С другого конца проблему решают Voila и Panel ( Voila нужно лихо, по-Д'Артаньяновски голосом Боярского произносить: «Вуаля!»). Voila идет от блокнота и поддерживает Jupyter interactive widgets с помощью которых может из вэб приложения общаться с кернелом, причем независимо от его языка (создатели говорят про независимость от языков, но для R не актуально у них есть Shiny, а на Julia бизнес аналитики не бывает). Вуаля позволяет делать интерактивный апп в два клика (не считая внедрения, например, ipywidgets, там кликов надо порядочно). Panel это решение сугубо для питона и идет к той же проблеме с другой стороны — от сервера, при этом собтвенно блокнот и Jupyter — опциональны. Модель можно сохранить в обычный питоновый файл и сервер не будет требовать всей Jupyter экосистемы. Panel не заточена под конкретную библиотеку для графики (примеры даются на matplotlib, bokeh, altair и plotly).

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

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

Сначала сделаем дашборд в Panel, потом используем Voila. Блокноты вместе с данными можно скачать с репозитория, или полистать в nbviewer ( panel, voila).

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

Для начала импортируем библиотеки и данные. Я буду использовать для графики Bokeh, потому что она у меня стандартно и есть заготовки для копипасты.

Далее заготовим несколько функций:

wm и std чтобы использовать их при группировке данных в pandas
default_graph и default_bar_plot — создают пустые заготовки графиков
color_picker — для распределения выбранных объектов по цветовой палитре

В основной части объявляем используемые виджеты

# declare panel widgets
multi_select = pn.widgets.MultiSelect(name='Model selection (Ctrl for multiple)', value=['opel corsa (FR)', 'citroen c3 (FR)'],
                                      options=list(raw_data['model'].unique()), size=8)
year_slider = pn.widgets.IntSlider(
    name='Year', start=2007, end=2016, step=1, value=2012)

checkbox = pn.widgets.Checkbox(name='Show trend error bars')

далее создаем функцию описываюсшую взаимодействия используя декоратор.

@pn.depends(multi_select.param.value, year_slider.param.value, checkbox.param.value)
def update(models, year, checkbox_status):

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

Внутри взаимодействия создаем наши заготовки графиков, далее для всех выбранных элементов наводим статистику, создаем элементы графика (линии, маркеры, стат погрешности),
собираем все в кучку и возвращаем графики как две вкладки для компактного показа.

   return pn.Tabs(('Distribution', bokehdist), ('Trend', bokehfig))

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

pn.Row(pn.Column('### Dashboard demo', multi_select,
                 year_slider, checkbox), update).servable()

Метод servable() делает наш дашборд доступным для panel сервера чтобы запускать
независимо из командной строки меняя настройки сервера. Если мы продолжаем работать с блокнотом, то нам в нем доступен весь интерактивный функционал. Для пробного просмотра того, как приложение будет выглядеть для внешнего пользователя добавляем метод show(). На этом все наши дополнительные усилия окончены, и они незначительно отличаются от того, чтобы просто построить графики.

Примерно так выглядит дашборд в блокноте.

image

Если мы хотим сделать дашборд доступным из-за пределов локалхоста надо разрешить обслуживать запросы извне, осторожным вайтлистингом или широким жестом типа

panel serve Dashboard_demo_panel.ipynb --allow-websocket-origin=*

Приложение которое увидит аналитик не отличается от того что в блокноте

image

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

Напоследок сравним как то же самое сделать с использованием Вуаля.
Версия с ipywidgets и bokeh у меня не взлетела, ругаясь на javascript в выводе.
Поэтому я перепилил ее на статичные графики matplotlib.

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

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

image

Лично по моим ощущениям — Panel явно победил по удобству использования. Тот же результат получился за сильно меньшее количество действий и дополнительные усилия чтобы его добавить к блокноту — минимальны. Так что все дружно и радостно переходим на панель!