Визуализация данных с помощью веб-фреймворка Dash

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Dash является довольно интересным Веб-фреймворком для визуализации данных и имеет в семе довольно много полезных функций в сочетании с простотой их применения.

Сам Dash это некий коллаб  HTML, React.Js, Flask  и CSS и предоставляет python классы для всех своих визуальных компонентов.

В качестве демонстративного датасета я возьму датасет diamonds с сайта kaggle (https://www.kaggle.com/shivam2503/diamonds)

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

Привожу пример сэмпла датасета

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
from dash.dependencies import Input, Output

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

В начале инициализируем класс dash, а также подгружаем dataset

app = dash.Dash(__name__)
df  = pd.read_csv('C://Users//User//Desktop//Учеба//diam.csv',sep = ';')

Далее создадим заголовок.

Для более красивого отображения, я использовал эти стили (https://github.com/matyushkin/lessons/blob/master/visualization/dash/avocado_analytics/apps/app_2/assets/style.css)

Определяем компонент html.Div а также вносим в него заголовок(html.h1) и абзац(html.P)

app.layout = html.Div(children=[

    html.Div(
        children=[
            html.H1(children='Analysis diamonds dataset', className= 'header-title'),


            html.P(children='maybe this demo will be useful to someone (:', className= 'header-description')и 
                ], className= 'header')])

ClassName является ссылкой на css файл

Который можно подгрузить внутрь проекта создав для него папку assets.

Вид структуры должен быть подобный

И запустим наше приложение

if __name__ == '__main__':
    app.run_server(debug=True)

Заголовок готов, теперь можно приступить к созданию объекта dropdown

Это будет меню для выбора необходимой гистограммы.

 

Данный элемент в коде будет выглядеть вот так

html.Div([
    dcc.Dropdown(
        id='demo_drop',
        options=[
            {'label': 'Огранка', 'value': 'cut'},
            {'label': 'Ясность(чистота)', 'value': 'clarity'},
            {'label': 'Цвет', 'value': 'color'}
        ],
        value='cut', className="dropdown"
    )])

В данном случае id означает уникальный идентификатор объекта он нам понадобится, когда будем описывать логику. Как можно понять из кода функционал данного объекта можно описать через словарь.  Атрибут value означает дефолтное выбранное значение.

Далее добавляем графический объект

dcc.Graph(id='output_graph')],className="card")

Пока что он пуст, но это только пока.

Далее нам нужно сделать так что бы наше приложение реагировало на запрос пользователя и для этого нужно использовать функции обратного вызова.  В них и будет описана связь между объектами Dropdown  и graph.

@app.callback(
 	   Output(component_id='output_graph', component_property='figure'),
    [	Input(component_id='demo_drop', component_property='value')]
)

В данном случае в input у нас заносится уникальный идентификатор dropdown объекта и его значения, которые мы описывали в словаре атрибута options.

А output возвращает гистограмму и ее значения.

Остается только прописать логику для обработки информации.

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

Для pandas это будет выглядеть вот так

h = df.groupby(['cut'], as_index=False, sort=False)['carat'].count()

Теперь вплетаем данное вычисление в функцию

def update_output(value):
    	if value == 'cut':
        		h = df.groupby(['cut'], as_index=False, sort=False)['carat'].count()
    	elif value == 'clarity':
        		h = df.groupby(['clarity'], as_index=False, sort=False)['carat'].count()
    	elif value == 'color':
        		h = df.groupby(['color'], as_index=False, sort=False)['carat'].count()
    	fig = px.bar(h, x=value, y="carat", labels = {"carat" : "Count"} )
    	 return fig

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

А переменная fig создает гистограмму

Таким образом у нас выходит такого вида интерфейс с выбором параметра группировки

Итоговый код

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
from dash.dependencies import Input, Output

 
app = dash.Dash(__name__)
df  = pd.read_csv('C://Users//User//Desktop//Учеба//diam.csv',sep = ';')
 
 
app.layout = html.Div(children=[


 
    html.Div(
        children=[
            html.H1(children='Analysis diamonds dataset', className= 'header-title'),
 

            html.P(children='maybe this demo will be useful to someone (:', className= 'header-description')
                ], className= 'header'),
 
    #html.Label('Количество'),
    html.Div([
        dcc.Dropdown(
            id='demo_drop',
            options=[
                {'label': 'Огранка', 'value': 'cut'},
                {'label': 'Ясность(чистота)', 'value': 'clarity'},
                {'label': 'Цвет', 'value': 'color'}
            ],
            value='cut', className="dropdown"
        ),  dcc.Graph(id='output_graph')],className="card")
 
])
@app.callback(
    Output(component_id='output_graph', component_property='figure'),
    [Input(component_id='demo_drop', component_property='value')]
)
def update_output(value):
    if value == 'cut':
        h = df.groupby(['cut'], as_index=False, sort=False)['carat'].count()
    elif value == 'clarity':
        h = df.groupby(['clarity'], as_index=False, sort=False)['carat'].count()
    elif value == 'color':
        h = df.groupby(['color'], as_index=False, sort=False)['carat'].count()
    fig = px.bar(h, x=value, y="carat", labels = {"carat" : "Count"} )
    return fig
 
if __name__ == '__main__':
    app.run_server(debug=True)

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

Источник: https://habr.com/ru/post/588645/


Интересные статьи

Интересные статьи

Используя машинное обучение, мы можем создать нашу собственную программу проверки на плагиат, которая выполняет поиск украденного контента в огромной базе данных. В этой статье мы сделаем  д...
Всем привет! Меня зовут Михаил Волошин, и я, как руководитель отдела инструментов бизнес-анализа, хочу верхнеуровнево рассказать о плюсах и особенностях BI-решения Yota. 200 Tb Ve...
Flutter предлагает различные виджеты для работы с определенным набором фигур, например, ClipRect, ClipRRect, ClipOval. Но также есть ClipPath, с помощью которого мы можем создавать ...
Проанализируем динамику акций аутсайдеров и лидеров Недавно прочитал статью о том, что акции-аутсайдеры (те, что максимально упали в цене за месяц) индекса Мосбиржи имеют бОльшие перспективы рос...
Годами эксперты в С++ рассуждают о семантике значений, иммутабельности и разделении ресурсов за счет коммуникации. О новом мире без мьютексов и гонок, без паттернов Command и Observer. На деле вс...