Время на прочтение
8 мин
Количество просмотров 6.4K
Использование интерфейса визуализации данных, также известное как создание дашбордов, является неотъемлемой частью набора навыков аналитиков данных. Дашборды и приложения для работы с данными используются сейчас повсеместно: от представления результатов анализа с помощью ряда визуальных образов до демонстрации ваших приложений машинного обучения.
Если речь идет о данных, значит, это касается и Python. В частности, мы говорим о библиотеке Dash, которая построена на базе одной из самых популярных библиотек для построения графиков — Plotly.
Dash позволяет легко создавать и делиться результатами анализа данных с помощью интерактивных дашбордов, используя только код Python. Нет необходимости изучать HTML, CSS или сложные JavaScript-фреймворки, такие как React.js.
В этом руководстве вы получите представление о том, на что способен Dash, и как интегрировать его в свой рабочий процесс.
Установка Dash и Plotly
Вы можете установить Dash с помощью pip
. Также необходимо инсталлировать библиотеку pandas для работы с наборами данных:
pip install dash pandas
Приведенная выше команда также выполняет установку plotly
. Plotly известен своими интерактивными графиками, и Plotly и Dash созданы Plotly Software Foundation, поэтому библиотеки довольно хорошо работают вместе.
Требования по использованию Dash
У такого мощного фреймворка, как Dash, есть несколько требований. Во-первых, вы должны знать Plotly Python, поскольку Dash может отображать только интерактивные графики Plotly.
Далее, вам необходимо базовое понимание HTML и CSS. Dash похож на React, но на языке Python. Это шаблонный фреймворк, на котором вы можете создать сайт без JavaScript.
Дашборд содержит множество графики, и пользователю самому решать, как отобразить все на одной странице. Plotly обрабатывает изображения, но аспект компоновки зависит от Dash и его HTML-компонентов.
Создание Dash-приложения
Давайте создадим наше Dash-приложение. После инсталляции импортируем следующие библиотеки:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
dash
– это глобальная библиотека, содержащая все основные функции. dash_core_components
и dash_html_components
– это библиотеки, которые устанавливаются с dash
по умолчанию. Они включают специфические для Dash фичи и Python-представление HTML-компонентов (тегов). Подробнее о них позже.
Любое приложение Dash запускается с помощью следующей команды:
app = dash.Dash(name="my_first_dash_app")
>>> app
<dash.dash.Dash at 0x1ee6af51af0>
Вышеприведенный код полностью создает бойлерплейт для чистого веб-сайта. Нам не нужна пустая страница, поэтому давайте заполним ее.
Сначала мы загрузим встроенный датасет из Plotly и создадим простую диаграмму рассеяния:
# Load dataset using Plotly
tips = px.data.tips()
fig = px.scatter(tips, x="total_bill", y="tip") # Create a scatterplot
Затем мы добавляем это изображение в атрибут layout
нашего приложения внутри тега div
с небольшими текстами:
app.layout = html.Div(children=[
html.H1(children='Hello Dash'), # Create a title with H1 tag
html.Div(children='''
Dash: A web application framework for your data.
'''), # Display some text
dcc.Graph(
id='example-graph',
figure=fig
) # Display the Plotly figure
])
if __name__ == '__main__':
app.run_server(debug=True) # Run the Dash app
Теперь мы создаем HTML-теги с помощью библиотеки dash_html_components (html)
, а изображение – используя основные компоненты (dcc) library
.
За тегом заголовка H1
следует div
, содержащий обычный текст, затем сам график с использованием функции Graph библиотеки dcc
. Все это находится внутри атрибута children
одного тега DIV.
В конце мы также добавляем команду, которая запускает наше приложение в режиме отладки, то есть изменения вступают в силу по мере внесения поправок в скрипт. Вот полный код на данный момент:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
# Create the app
app = dash.Dash(__name__)
# Load dataset using Plotly
tips = px.data.tips()
fig = px.scatter(tips, x="total_bill", y="tip") # Create a scatterplot
app.layout = html.Div(children=[
html.H1(children='Hello Dash'), # Create a title with H1 tag
html.Div(children='''
Dash: A web application framework for your data.
'''), # Display some text
dcc.Graph(
id='example-graph',
figure=fig
) # Display the Plotly figure
])
if __name__ == '__main__':
app.run_server(debug=True) # Run the Dash app
Поместите его в скрипт Python и запустите. В терминале вы получите сообщение о том, что необходимо перейти по этой ссылке: http://127.0.0.1:8050/.
Итак, поехали:
В следующих разделах мы подробно расскажем о том, что здесь произошло.
Создание app.layout
Давайте начнем с атрибута layout
. Это единственный атрибут, который содержит все ваши HTML-компоненты и изображения. Вы должны передать ему всю вашу графику и HTML-теги в конечном теге DIV.
В зависимости от размера вашего проекта, данный атрибут может стать довольно большим, поэтому я рекомендую создавать все ваши HTML-теги и фигуры в отдельных переменных, а затем передавать их в layout
.
Например, вот как будет выглядеть приведенное выше приложение:
app = dash.Dash(name="app")
# Load dataset using Plotly
tips = px.data.tips()
fig = px.scatter(tips, x="total_bill", y="tip") # Create a scatterplot
title = html.H1("Hello Dash!")
text_div = html.Div("Dash: A web application framework for your data.")
graph_to_display = dcc.Graph(id="scatter", figure=fig)
app.layout = html.Div(children=[title, text_div, graph_to_display])
Это гораздо аккуратнее и компактнее, и это одна из тех вещей, о которых вы не узнаете в документации Dash. Там куча вложенного кода вместо того, чтобы сделать вышеописанное.
Компоненты HTML и CSS в Dash
Давайте обсудим, как HTML и CSS работают в Dash. Подбиблиотека dash_html_components
содержит наиболее распространенные теги HTML, такие как divs, кнопки, текстовые поля, названия, теги заголовков (H1-6) и т. д.
Они реализованы в коде Python под соответствующими именами как представление их HTML-аналогов. Итак, код, подобный приведенному, ниже:
import dash_html_components as html
html.Div([
html.H1('Hello Dash'),
html.Div([
html.P('Dash converts Python classes into HTML'),
html.P("This conversion happens behind the scenes by Dash's JavaScript frontend")
])
])
Будет интерпретироваться вашим браузером следующим образом:
<div>
<h1>Hello Dash</h1>
<div>
<p>Dash converts Python classes into HTML</p>
<p>This conversion happens behind the scenes by Dash's JavaScript front-end</p>
</div>
</div>
Все HTML-теги этой подбиблиотеки содержат следующие основные аргументы:
-
id
: то же, что и атрибутid
HTML-тегов -
className
: то же самое, что и атрибутclass
тегов HTML -
style
: такой же, как атрибутstyle
тегов HTML, но принимает только словарь стилей CSS -
children
: первый аргумент большинства компонентов HTML
Вот пример div
с некоторыми кастомизированными настройками:
app = dash.Dash(name="app")
app.layout = html.Div(
children=html.H3("Simple Div"),
id="sample_div",
className="red_div",
style={"backgroundColor": "red"},
)
if __name__ == "__main__":
app.run_server(debug=True)
Аргумент children
уникален — он может принимать числа и строки, но чаще всего вы передаете другие компоненты HTML списком, если это тег-контейнер, например такой как div.
Замечание о стилях CSS: большинство атрибутов стиля CSS используют дефисы для разделения слов. Когда вы передаете их в аргумент style Dash
, они должны применять camelCase
, например backgroundColor
вместо background-color
.
Я настоятельно рекомендую вам изучить данные HTML-теги, поскольку это единственное, что сохраняет целостность макета (лейаута) вашего приложения. Вот полный список HTML-тегов, поддерживаемых Dash.
Основные компоненты Dash
Другой важной частью Dash являются его основные компоненты. Библиотека dash_core_components
содержит несколько других HTML-тегов, но в нее уже встроено немного CSS и JavaScript.
Некоторые примеры включают выпадающие списки, слайдеры, функционалы загрузки и выгрузки, а также компонент для отображения графиков Plotly.
Вот несколько образцов этих компонентов, начиная с выпадающего списка:
import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Dropdown(
options=[
{'label': 'FC Barcelona', 'value': 'FCB'},
{'label': 'Real Madrid', 'value': 'RM'},
{'label': 'Manchester United', 'value': 'MU'}
],
value='FCB' # The default value to display
)
])
Выпадающий список с мультивыбором:
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Dropdown(
options=[
{'label': 'FC Barcelona', 'value': 'FCB'},
{'label': 'Real Madrid', 'value': 'RM'},
{'label': 'Manchester United', 'value': 'MU'}
],
multi=True,
value="FCB"
)
], style={"width": 200})
if __name__ == '__main__':
app.run_server(debug=True)
Слайдер с помеченными точками останова:
import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Slider(
min=0,
max=9,
marks={i: 'Label{}'.format(i) for i in range(10)},
value=5,
)
])
if __name__ == '__main__':
app.run_server(debug=True)
Существует универсальный атрибут value, который представляет дефолтное значение при первом рендеринге компонента.
Полный список основных компонентов можно посмотреть здесь.
Создание финального интерфейса визуализации данных с помощью Python Dash
В качестве завершающего примера посмотрите на приведенное ниже приложение:
import seaborn as sns
app = dash.Dash(__name__)
diamonds = sns.load_dataset("diamonds")
scatter = px.scatter(
data_frame=diamonds,
x="price",
y="carat",
color="cut",
title="Carat vs. Price of Diamonds",
width=600,
height=400,
)
histogram = px.histogram(
data_frame=diamonds,
x="price",
title="Histogram of Diamond prices",
width=600,
height=400,
)
violin = px.violin(
data_frame=diamonds,
x="cut",
y="price",
title="Violin Plot of Cut vs. Price",
width=600,
height=400,
)
left_fig = html.Div(children=dcc.Graph(figure=scatter))
right_fig = html.Div(children=dcc.Graph(figure=histogram))
upper_div = html.Div([left_fig, right_fig], style={"display": "flex"})
central_div = html.Div(
children=dcc.Graph(figure=violin),
style={"display": "flex", "justify-content": "center"},
)
app.layout = html.Div([upper_div, central_div])
if __name__ == "__main__":
app.run_server(debug=True)
Мы импортируем датасет Diamonds из Seaborn и создаем три графика: диаграмму рассеяния, гистограмму и скрипичную диаграмму. Мы хотим отобразить график рассеяния и гистограмму рядом друг с другом и поместить скрипичную диаграмму прямо под ними в центре.
Для этого мы создаем два div’а, содержащих график рассеяния и гистограмму, left_figure
и right_figure
. Затем для простоты эти два div помещаем в еще один div — upper_div
.
Мы устанавливаем CSS-стиль flex-box для этого div, который размещает фигуры бок о бок.
Затем мы создаем центральный div, содержащий скрипичную диаграмму, и выравниваем его по центру с помощью flex-box и его атрибута justify-content.
Наконец, мы помещаем все в лейаут внутри последнего DIV и запускаем скрипт. Вот конечный результат:
Заключение
Вот краткое описание шагов по созданию базового Dash-приложения:
-
Создайте приложение с помощью
dash.Dash
и дайте ему любое название. -
Набросайте лейаут своих графиков в дашборде, прежде чем писать код.
-
Создайте графики, которые войдут в ваш дашборд
-
Создайте шаблонный лейаут с помощью HTML-компонентов Dash
-
Добавьте свои изображеня в соответствующие контейнеры
-
Наконец, добавьте все HTML-компоненты к атрибуту лейаута
Несмотря на то, что мы рассмотрели многие базовые аспекты, такие как HTML, основные компоненты и лейаут приложения, это лишь поверхностное знакомство с возможностями Dash.
Я показал вам множество примеров интерактивных HTML-компонентов, но не рассказал, как интегрировать их в ваше приложение. Как вы можете обновлять графики на основе вводимых пользователем данных, таких как слайдеры, текст или что-то подобное?
Вот здесь-то и приходят на помощь коллбеки. Это очень мощная и основная фича Dash. Чтобы использовать коллбеки, вы определяете в Dash функции, которые выстреливают при изменении компонента пользователем, и функция модифицирует новый компонент на основе этого события.
Dash посвящает большой раздел в документации только для объяснения коллбеков, поскольку поначалу в них трудно разобраться. Я предлагаю вам обратиться к этой теме на следующем этапе.
Загляните в галерею примеров, где вы сможете увидеть и насладиться некоторыми очень крутыми проектами, созданными с помощью Dash. Самое приятное, что многие из них с открытым исходным кодом, а это значит, что вы можете многое для себя почерпнуть и вдохновиться на новые идеи.
Спасибо за прочтение!
В заключение приглашаем на открытое занятие «Работа с Power BI. Построение дашборда. Настройка и взаимодействие визуальных элементов». На уроке загрузим данные в Power BI Desktop из источника, построим небольшой дашборд, посмотрим на назначение и варианты настройки базовых визуальных элементов. Записаться можно по ссылке.
Sept. 6, 2021
I don’t have to convince you why we need an interactive dashboard. But most people don’t know that they don’t have to buy expensive licenses of Tableau or PowerBI. You don’t have to enroll in a JavaScript course, either.
Dash apps allow you to build interactive dashboards purely in Python. Interestingly, it could reach heights that popular BI platforms can not.
Unlike other tools to create dashboard web applications, you can host Dash apps on your servers and terms. You can use this tool for various use cases, from a key performance indicator dashboard for your employees that changes once a month to a real-time network monitoring dashboard.
I strongly recommend the book, Interactive Dashboards and Data Apps with Plotly and Dash because it gives an in-depth understanding of interactive dashboard design.
Other resources about Dashboards and Data Visualization:
The Big Book of Dashboards
Storytelling with Data
Why Dash? Why not Tableau, Power BI, or some JavaScript library?
BI Platforms such as Tableau and PowerBI do a fantastic job. It allows even non-technical managers to do data exploration themselves. I don’t have complaints about them.
They are excellent tools for performing analysis on read-only datasets. But in a large data science project, you’ll have to perform complex actions. For instance, you must trigger a backend function and start the model retraining.
In such cases, my best solution was to build a web app from scratch. JavaScript data visualization libraries such as HighCharts are excellent tools for this. They have callbacks for almost every possible user action. I use them to send data back to the server and control it better.
Related: How to Make a PDF Text-to-Speech Reader in Python
But this wasn’t a walk in the park. My data science team is exceptional in Python and R but not JavaScript. Not on web frameworks such as Django either. And that’s not enough; to build modern web apps, you need frontend web frameworks such as React.
As we progressed, we realized the harsh truth. Every new technology in our stack inflates the difficulty exponentially.
And we were fortunate to find Dash—a pure Python open-source web dashboard framework. If you’re comparing Plotly dash vs. react, Dash is built using react, so you don’t have to do the heavy lifting for yourself.
Now, this is how I create my own web dashboards in Python. If you’re looking for a lightweight alternative, check out Streamlit.
Read along if you need flexible, custom dashboards entirely in Python. There’s also an amazing extension to this package that lets you create Dash apps inside Jupyter notebooks. See its repository for more Jupiter dashboard examples.
Streamlit vs. Dash vs. Gradio
Both tools are great for building a dashboard web application. But streamlit is more focused on building quick control panels for ML projects. Plotly is excellent for building cool dashboards at ease.
Another excellent alternative to creating a dashboard web application is Gradio. With gradio, you can even create a dashboard in python Jupiter notebook.
If you create your web dashboard app in either Streamlit or Gradio, it could also work on mobile devices. Your Plotly dashboard app may need a bit more optimization for this.
Building your first dashboard in Python (in less than 1 minute.)
Yes, building dashboards in Dash is that simple. Install Pandas and dash with the following command, then start the timer.
pip install dash pandas
Create a file called app.py
in your project directory with the content below.
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
app = dash.Dash()
df = pd.read_csv(
"https://raw.githubusercontent.com/ThuwarakeshM/geting-started-with-plottly-dash/main/life_expectancy.csv"
)
fig = px.scatter(
df,
x="GDP",
y="Life expectancy",
size="Population",
color="continent",
hover_name="Country",
log_x=True,
size_max=60,
)
app.layout = html.Div([dcc.Graph(id="life-exp-vs-gdp", figure=fig)])
if __name__ == "__main__":
app.run_server(debug=True)
Showtime! let’s run the dashboard app with the following command:
python app.py
You’ll see it starting a server at port 8050. If you visit http://127.0.0.1:8050 on your browser, you’d see the dashboard that looks like the following:
You’d appreciate the difference if you’ve created a similar app using JavaScript libraries. Dash saves a ton of time by eliminating an incredible amount of boilerplate code. Even popular BI tools have lots of prework to get to this point.
Awesome. That’s quite a thing for inspiring you to build dashboards. But you might have realized that it’s not dazzling yet. In the following sections, we’ll discuss how
- we can improve the layout;
- add interactions and callbacks to the widgets like google analytics and;
- style the app further.
With this, you can create the dazzling dashboard you need. Browse the Plottly Dash gallery for more of such dashboards for inspiration.
Related: 7 Ways to Make Your Python Project Structure More Elegant
Let’s add more widgets to the layout.
Dash follows an HTML-like element hierarchy. You can attach any of Dash’s HTML or Core components to the layout property of the app. The layout property is the root of a Dash app’s element hierarchy.
Core components are a pre-configured set of widgets such as dropdowns and sliders.
Dash’s HTML components cover almost every HTML element available. To create a heading, you can use html.H1
and html.P
to create a paragraph. The children attribute allows you to nest one HTML component within another.
app.layout = html.Div(
[
# Dropdown to filter developing/developed country.
html.Div(
[
dcc.Dropdown(
id="status-dropdown",
options=[{"label": s, "value": s} for s in df.Status.unique()], # Create available options from the dataset
),
]
),
# Dropdown to filter countries with average schooling years.
html.Div(
[
dcc.Dropdown(
id="schooling-dropdown",
options=[
{"label": y, "value": y}
for y in range(
int(df.Schooling.min()), int(df.Schooling.max()) + 1
)
], # add options from the dataset.
),
]
),
# Placeholder to render teh chart.
html.Div(dcc.Graph(id="life-exp-vs-gdp"), className="chart"),
# Slider to select year.
dcc.Slider(
"year-slider",
min=df.Year.min(), # dynamically select minimum and maximum years from the dataset.
max=df.Year.max(),
step=None,
marks={year: str(year) for year in range(df.Year.min(), df.Year.max() + 1)}, # set markers at one year interval.
value=df.Year.min(),
),
],
)
In the above code, we’ve included three core components—two dropdowns and a slider. These controller elements allow us to filter the chart data and create interactivity in the next section.
Adding interactivity with component callbacks.
Dash’s core components have callbacks to control the response for a user action. This feature is remarkable of why Dash apps outshine popular BI platforms.
You can use this call back to control a chart re-rendering or trigger a heavy analysis. Check out my article on performing massive computations to use with Dash apps and Celery.
Here in this post, we use callbacks to filter the chart data.
@app.callback(
Output("life-exp-vs-gdp", "figure"),
Input("year-slider", "value"),
Input("status-dropdown", "value"),
Input("schooling-dropdown", "value"),
)
def update_figure(selected_year, country_status, schooling):
filtered_dataset = df[(df.Year == selected_year)]
if schooling:
filtered_dataset = filtered_dataset[filtered_dataset.Schooling <= schooling]
if country_status:
filtered_dataset = filtered_dataset[filtered_dataset.Status == country_status]
fig = px.scatter(
filtered_dataset,
x="GDP",
y="Life expectancy",
size="Population",
color="continent",
hover_name="Country",
log_x=True,
size_max=60,
)
return fig
The callback function is annotated with the @app.callback
decorator. The first argument of this decorator is the Output component in the element tree. We need to specify the id of that element and the property we need to change. This property will change to the return value of the callback function.
Then the decorated will accept any number of input arguments. Each will be tied to a core component as we attached the output component. We can specify the element’s id and the property that emits the change value. Usually, this would be ‘value.’
Each input in the decorator should have a respective argument in the callback function’s definition.
Finally, we moved the figure component inside the callback function. Every time we run the callback function, it creates a new figure instance and updates the UI.
Let’s Style your dashboard (in Python; no CSS.)
You can use the inline styling options available in Dash app. But with little CSS, you could have spectacular results.
In-dash, you can style elements in three different ways.
Inline styling
Every Dash py component accepts a style argument. You can pass a dictionary and style any element. This is the most convenient way to style a Dash app.
html.H1("My Dazzling Dashboard", style={"color": "#011833"}),
Local stylesheets (okay, some CSS if you need.)
Alternatively, you can pass a class name attribute to any Dash component and use a separate CSS file to style it. You should place this CSS file inside an asset folder in your project directory. Dash will automatically pick it and apply its styles to the components.
# - app.py
# - assets/
# |-- style.css
# style.css
# -----------------------------------------
# .title { color: #011833 }
# app.py
html.H1("My Dazzling Dashboard", className='title')
External stylesheets.
You can also use stylesheets from the internet. For instance, dash has this preconfigured stylesheet with convenient utility classes. You can specify the style sheet and use its class names in elements to make them beautiful.
app = dash.Dash(
__name__, external_stylesheets="https://codepen.io/chriddyp/pen/bWLwgP.css"
)
# Alternative way
app.css.append_css({
"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})
final project — creating visualizations and dashboards
Here is the complete styled source code of the application. We’ve used a local stylesheet and organized the HTML to support styling. The full code and the local stylesheet are in this GitHub repository.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash_html_components.Label import Label
from pandas.io.formats import style
import plotly.express as px
import pandas as pd
from dash.dependencies import Input, Output
app = dash.Dash(
__name__,
)
df = pd.read_csv(
"https://raw.githubusercontent.com/ThuwarakeshM/geting-started-with-plottly-dash/main/life_expectancy.csv"
)
colors = {"background": "#011833", "text": "#7FDBFF"}
app.layout = html.Div(
[
html.H1(
"My Dazzling Dashboard",
),
html.Div(
[
html.Div(
[
html.Label("Developing Status of the Country"),
dcc.Dropdown(
id="status-dropdown",
options=[
{"label": s, "value": s} for s in df.Status.unique()
],
className="dropdown",
),
]
),
html.Div(
[
html.Label("Average schooling years grater than"),
dcc.Dropdown(
id="schooling-dropdown",
options=[
{"label": y, "value": y}
for y in range(
int(df.Schooling.min()), int(df.Schooling.max()) + 1
)
],
className="dropdown",
),
]
),
],
className="row",
),
html.Div(dcc.Graph(id="life-exp-vs-gdp"), className="chart"),
dcc.Slider(
"year-slider",
min=df.Year.min(),
max=df.Year.max(),
step=None,
marks={year: str(year) for year in range(df.Year.min(), df.Year.max() + 1)},
value=df.Year.min(),
),
],
className="container",
)
@app.callback(
Output("life-exp-vs-gdp", "figure"),
Input("year-slider", "value"),
Input("status-dropdown", "value"),
Input("schooling-dropdown", "value"),
)
def update_figure(selected_year, country_status, schooling):
filtered_dataset = df[(df.Year == selected_year)]
if schooling:
filtered_dataset = filtered_dataset[filtered_dataset.Schooling <= schooling]
if country_status:
filtered_dataset = filtered_dataset[filtered_dataset.Status == country_status]
fig = px.scatter(
filtered_dataset,
x="GDP",
y="Life expectancy",
size="Population",
color="continent",
hover_name="Country",
log_x=True,
size_max=60,
)
fig.update_layout(
plot_bgcolor=colors["background"],
paper_bgcolor=colors["background"],
font_color=colors["text"],
)
return fig
if __name__ == "__main__":
app.run_server(debug=True)
Your web app refreshes as you update your code with the above. And it may look like the below—your first version of a dazzling dashboard.
What next in your Dash app journey?
Dash is no doubt the best web dashboard framework for Python developers. Check out the Dash Enterprise App Gallery for more Python dash examples.
A vital benefit of these gallery apps is that they are a rich repository of dash layout examples.
If you’d like to take your Dash skills to the next level, check out this popular course on Udemy. More than 42k people benefited from this course, and about 7.8k rated this course 4.7 stars.
It’s a beneficial resource if you’ve questions about adding authorization to the app or cloud deployment.
Final Thoughts
Plotly, Dash apps are an incredible tool for Python developers. Since most data science teams do not specialize in JavaScript, building dashboards with Dash saves much of their time.
We can use Tableau, PowerBI, and similar BI platforms for data exploration and visualization. But Dash apps outshine them as they tightly integrate with the backend code.
In this article, we explored the surface of Dash apps. I trust this would’ve given you the kickstart to build outstanding dashboards without worrying about scary technology stacks.
As a next step, I strongly recommend exploring Dash’s documentation page and its example gallery.
Веб-разработка с Python: Dash (полное руководство)
Рисование с помощью Plotly, внедрение Bootstrap CSS, загрузка и скачивание файлов, изменение ввода после выбора, панели навигации, счетчики и многое другое…
Резюме
Добро пожаловать в это хардкорное руководство по Dash. После этой статьи вы сможете создать и развернуть базовый прототип (минимально жизнеспособный продукт) для любого типа веб-приложения.
По случаю свадьбы моего лучшего друга я попытался облегчить ему жизнь с помощью приборной панели для расстановки сидений. Во время написания кода я понял, что этот простой проект содержит все ключевые функции, необходимые для разработки базового, но хорошего прототипа. Поэтому я подумал, что стоит поделиться им.
В этом руководстве я объясню, как создать полноценное веб-приложение Dash, на примере моего приложения для планирования свадеб (ссылка ниже).
Я представлю некоторый полезный код Python, который можно легко применить в других подобных случаях (просто скопировать, вставить, запустить) и пройтись по каждой строке кода с комментариями, чтобы вы могли воспроизвести этот пример (ссылка на полный код ниже).
В частности, я пройду через:
- Настройка среды
- Модель данных
- Подготовить базовую структуру приложения тире (панель навигации, тело, макет)
- Входные данные (форма, ползунок, руководство, загрузка файла, изменение входных данных после события)
- Вывод (Plotly, загрузка файла, счетчик при загрузке)
- Разверните приложение на Heroku
Настраивать
Первым делом я установлю через терминал следующие библиотеки:
## for application dash==1.20.0 dash-bootstrap-components==0.12.2 ## to produce random data names==0.3.0 ## for data processing numpy==1.19.5 pandas==1.1.5 ## for plotting plotly==4.14.3 ## for read and write excel files openpyxl==3.0.7 xlrd==1.2.0
Чтобы панель управления выглядела красиво, мы будем использовать Bootstrap, фреймворк CSS / JS, который содержит шаблоны дизайна для форм, кнопок, навигации и других компонентов интерфейса . Пакет D ash-Bootstrap-Components позволяет легко интегрировать Bootstrap в наше приложение Dash.
Пакет names генерирует случайные имена, и я буду использовать его для создания набора данных случайных гостей.
Обратите внимание, что последняя версия xlrd (2.0.0) не принимает файлы .xlsx, поэтому используйте 1.2.0 если вы хотите загрузить файлы Excel.
Модель данных
Вкратце, идея состоит в том, чтобы создать случайный список гостей и запустить алгоритм оптимизации для расстановки мест. В качестве альтернативы мы дадим пользователям возможность загрузить свой файл Excel, и алгоритм будет использовать его вместо случайного набора данных.
import names import pandas as pd import numpy as np ''' Generate random guests list :parameter :param n: num - number of guests and length of dtf :param lst_categories: list - ["family", "friends", ...] :param n_rules: num - number of restrictions to apply (ex. if 1 then 2 guests can't be sit together) :return dtf with guests ''' def random_data(n=100, lst_categories=["family","friends", "work","university","tennis"], n_rules=0): ## basic list lst_dics = [] for i in range(n): name = names.get_full_name() category = np.random.choice(lst_categories) if len(lst_categories) > 0 else np.nan lst_dics.append({"id":i, "name":name, "category":category, "avoid":np.nan}) dtf = pd.DataFrame(lst_dics) ## add rules if n_rules > 0: for i in range(n_rules): choices = dtf[dtf["avoid"].isna()]["id"] ids = np.random.choice(choices, size=2) dtf["avoid"].iloc[ids[0]] = int(ids[1]) if int(ids[1]) != ids[0] else int(ids[1])+1 return dtf
Эта функция создает таблицу с информацией о гостях.
Я воспользуюсь столбцом «Категория», чтобы отображать гостей разными цветами:
Столбец «избегать» будет использоваться для того, чтобы два гостя, ненавидящие друг друга, не оказались за одним столом.
Приложение будет распределять места на основе:
- награда +1, когда два человека, принадлежащих к одной категории, сидят рядом друг с другом
- штраф -1, когда два человека, которые хотят избежать друг друга, помещаются за один стол.
Эта функция возвращает тот же фрейм данных с новым столбцом для назначенной таблицы:
Структура приложения
Теперь мы можем начать с самой интересной части: создания приложения. Я разделю его на 3 части: панель навигации, тело и макет. Причем каждый раздел будет состоять из 3 частей:
- Ввод — раздел приложения, в котором пользователь может вставлять и выбирать параметры и данные, которые будут использоваться серверной частью для возврата желаемого результата (для панели навигации ввод не требуется).
- Вывод — раздел приложения, в котором пользователь может визуализировать результаты.
- Обратные вызовы — декоратор, оборачивающий функцию, в которой нужно указать выходы, входы и состояния; последние позволяют передавать дополнительные значения без использования обратных вызовов (обратные вызовы могут выглядеть пугающе, но на самом деле они ваши лучшие друзья).
# setup import dash from dash.dependencies import Input, Output, State import dash_core_components as dcc import dash_html_components as html import dash_bootstrap_components as dbc # App Instance app = dash.Dash(name="name") app.title = "name" ########################## Navbar ########################## # Input # Output navbar = dbc.Nav() # Callbacks @app.callback() def function(): return 0 ########################## Body ########################## # Input inputs = dbc.FormGroup() # Output body = dbc.Row([ ## input dbc.Col(md=3), ## output dbc.Col(md=9) ]) # Callbacks @app.callback() def function(): return 0 ########################## App Layout ########################## app.layout = dbc.Container(fluid=True, children=[ html.H1("name", id="nav-pills"), navbar, html.Br(),html.Br(),html.Br(), body ]) ########################## Run ########################## if __name__ == "__main__": app.run_server(debug=True)
Начнем со стиля . Замечательный Dash-Bootstrap-Components предлагает огромное разнообразие предопределенных стилей. Вы можете ознакомиться с ними здесь. Выбрав один из них, вы можете вставить его в экземпляр приложения как внешнюю таблицу стилей. Вы даже можете использовать более одного:
theme = dbc.themes.LUX css = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css' # App Instance app = dash.Dash(name="name", external_stylesheets=[theme, css])
Перейдем к верхней панели навигации. Я добавлю ссылку, всплывающее окно и раскрывающееся меню.
Как видите, панель навигации классная и реагирует на нажатие, с всплывающими окнами и раскрывающимся меню. Выпадающее меню «Ссылки» очень простое, так как для его работы не требуется обратный вызов, а всплывающее меню «О программе» немного сложно.
Навигационная панель содержит 3 навигационных элемента: логотип, кнопку «О программе», раскрывающееся меню. Кнопка «О программе» включает в себя 2 элемента: навигационную ссылку (которая обычно используется для навигации по многостраничному приложению, но в данном случае href = ”/”) и всплывающее окно (зеленый и красный Метки). Эти 2 элемента вызываются в обратном вызове как выходы, входы и состояния, как это, если щелкнуть навигационную ссылку «О программе», тогда всплывающее окно станет активным и появится. Функция python about_popover () ожидает 3 аргумента, потому что обратный вызов имеет один вход и два состояния, и возвращает 2 переменные, поскольку обратный вызов имеет два выхода. Когда приложение запускается и кнопка не нажимается n = 0.
Обратите внимание, что раскрывающееся меню (синяя часть) включает шрифты, импортированные с помощью внешней таблицы стилей (т. Е. className = ”fa fa-linkedin”).
Панель навигации, которую мы только что видели, является одним из элементов окончательного макета вместе с заголовком и основным телом:
Теперь поговорим о слоне в комнате… основном теле. Он состоит из входов (слева) и выходов (справа), которые взаимодействуют друг с другом благодаря обратным вызовам.
Входы
Обычно входные данные объединяются в группу форм и отправляются при нажатии кнопки Форма. Ползунки и ввод вручную — самые распространенные элементы формы.
Вот как можно создать обычный слайдер:
dcc.Slider(id="n-guests", min=10, max=100, step=1, value=50, tooltip={'always_visible':False})
и вот как установить в ползунке только определенные значения:
dcc.Slider(id="n-iter", min=10, max=1000, step=None, marks={10:"10", 100:"100", 500:"500", 1000:"1000"}, value=0),
Это простой ручной ввод:
dbc.Input(id="max-capacity", placeholder="table capacity", type="number", value="10"),
Давайте увеличим сложность и разберемся с ситуацией «Загрузка файла». Я собираюсь дать пользователям возможность загрузить файл Excel, содержащий аналогичный набор данных, который мы сгенерировали случайным образом:
При загрузке файла я хочу, чтобы произошло два события:
- отображать имя файла, чтобы быть уверенным, что был выбран правильный и он был правильно загружен
- скрыть первые два ползунка, потому что они предназначены для случайного моделирования и становятся бесполезными при загрузке настраиваемого файла
Как нам этого добиться? Легко, с волшебным обратным вызовом, который изменяет стиль CSS компонентов HTML:
Чтобы использовать загруженный файл, нам нужно проанализировать его и преобразовать в фрейм данных pandas, и мы собираемся использовать для этого эту функцию:
import pandas as pd import base64 import io ''' When a file is uploaded it contains "contents", "filename", "date" :parameter :param contents: file :param filename: str :return pandas table ''' def upload_file(contents, filename): content_type, content_string = contents.split(',') decoded = base64.b64decode(content_string) try: if 'csv' in filename: return pd.read_csv(io.StringIO(decoded.decode('utf-8'))) elif 'xls' in filename: return pd.read_excel(io.BytesIO(decoded)) except Exception as e: print("ERROR:", e) return 'There was an error processing this file.'
Прежде чем перейти к выводам, давайте подведем итоги того, что мы видели до сих пор. Вот полный код входов в основном теле:
########################## Body ########################## # Input inputs = dbc.FormGroup([ ## hide these 2 inputs if file is uploaded html.Div(id='hide-seek', children=[ dbc.Label("Number of Guests", html_for="n-guests"), dcc.Slider(id="n-guests", min=10, max=100, step=1, value=50, tooltip={'always_visible':False}), dbc.Label("Number of Rules", html_for="n-rules"), dcc.Slider(id="n-rules", min=0, max=10, step=1, value=3, tooltip={'always_visible':False}) ], style={'display':'block'}), ## always visible dbc.Label("Number of Trials", html_for="n-iter"), dcc.Slider(id="n-iter", min=10, max=1000, step=None, marks={10:"10", 100:"100", 500:"500", 1000:"1000"}, value=0), html.Br(), dbc.Label("Max Guests per Table", html_for="max-capacity"), dbc.Input(id="max-capacity", placeholder="table capacity", type="number", value="10"), ## upload a file html.Br(), dbc.Label("Or Upload your Excel", html_for="upload-excel"), dcc.Upload(id='upload-excel', children=html.Div([ 'Drag and Drop or ', html.A('Select Files')]), style={'width':'100%', 'height':'60px', 'lineHeight':'60px', 'borderWidth':'1px', 'borderStyle':'dashed', 'borderRadius':'5px', 'textAlign':'center', 'margin':'10px'} ), html.Div(id='excel-name', style={"marginLeft":"20px"}), ## run button html.Br(),html.Br(), dbc.Col(dbc.Button("run", id="run", color="primary")) ]) # Callbacks @app.callback( output=[ Output(component_id="hide-seek", component_property="style"), Output(component_id="excel-name", component_property="children")], inputs=[ Input(component_id="upload-excel",component_property="filename")]) def upload_event(filename): div = "" if filename is None else "Use file "+filename return {'display':'block'} if filename is None else {'display':'none'}, div
Выходы
Серверная часть должна выдавать 3 вывода: заголовок, ссылку для загрузки результатов в виде файла Excel и, очевидно, график.
Приступим к сюжету, сделанному с помощью Plotly. По сути, есть два основных модуля этой удивительной графической библиотеки: plotly express и graph_objects. Первый — это графический инструмент высокого уровня, содержащий функции, которые могут создавать целые фигуры сразу (я нахожу это похожим на seaborn), в то время как последний позволяет вам строить фигуру по кирпичику (на самом деле это то, что сюжетно выражает работает под капотом).
Экспресс-график идеально подходит, если вы хотите стилизовать данные на основе значений определенных столбцов, поэтому здесь я собираюсь использовать это, но если вы хотите увидеть примеры графиков, созданных с помощью graph_objects, ознакомьтесь с «эта статья».
Итак … что это?
Это может выглядеть как рисунок, но это правильная геометрическая фигура: это диаграмма рассеяния, цвет на которой основан на категории, к которой принадлежат гости (семья, друзья,…), размер определяется тем, хочет ли гость избегать кого-то. или нет (в основном я выделяю проблемные), а фасетный компонент связан с таблицей, назначенной каждому гостю. Фасетные графики — это фигуры, составленные из нескольких подзаголовков, которые имеют одинаковый набор осей, где каждый подзаголовок показывает подмножество данных.
Прежде всего, мне нужно добавить координаты x и y для графика, используя уравнение круга: (x, y) = (r * cosθ, r * sinθ). Затем я добавляю столбец «размер» на основе столбца «избегать»:
def prepare_data(dtf): ## mark the rules dtf["avoid"] = dtf["avoid"].apply(lambda x: dtf[dtf["id"]==x]["name"].iloc[0] if pd.notnull(x) else "none") dtf["size"] = dtf["avoid"].apply(lambda x: 1 if x == "none" else 3) ## create axis dtf_out = pd.DataFrame() lst_tables = [] for t in dtf["table"].unique(): dtf_t = dtf[dtf["table"]==t] n = len(dtf_t) theta = np.linspace(0, 2*np.pi, n) dtf_t["x"] = 1*np.cos(theta) dtf_t["y"] = 1*np.sin(theta) dtf_out = dtf_out.append(dtf_t) return dtf_out.reset_index(drop=True).sort_values("table")
Затем я могу просто использовать команды plotly для создания фигур и указать, какая информация будет отображаться при наведении указателя мыши на точки:
import plotly.express as px fig = px.scatter(dtf, x="x", y="y", color="category", hover_name="name", facet_col="table", facet_col_wrap=3, size="size", hover_data={"x":False, "y":False, "category":True, "avoid":True, "size":False, "table":False} ) fig.add_shape(type="circle", opacity=0.1, fillcolor="black", col="all", row="all", exclude_empty_subplots=True, x0=dtf["x"].min(), y0=dtf["y"].min(), x1=dtf["x"].max(), y1=dtf["y"].max() ) fig.update_layout(plot_bgcolor='white', legend={"bordercolor":"black", "borderwidth":1, "orientation":"h"} )
Полный код для сюжета (и заголовок):
Теперь, когда график готов, как загрузить результаты в виде файла Excel? Нам просто нужна функция, которая преобразует фрейм данных pandas в файл и передает ссылку для его загрузки в пользовательский интерфейс:
import pandas as pd import io import base64 ''' Write excel :parameter :param dtf: pandas table :return link ''' def download_file(dtf): xlsx_io = io.BytesIO() writer = pd.ExcelWriter(xlsx_io) dtf.to_excel(writer, index=False) writer.save() xlsx_io.seek(0) media_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' data = base64.b64encode(xlsx_io.read()).decode("utf-8") link = f'data:{media_type};base64,{data}' return link
На стороне интерфейса мы должны добавить HTML-ссылку для загрузки и проделать обычный трюк с обратным вызовом:
Как вы могли заметить, выходные данные (заголовок, загрузка, сюжет) заключены в Spinner, который воспроизводит этот приятный эффект состояния загрузки при разработке входных данных:
Развертывать
Наконец, мы готовы развернуть это приложение. Вот полный код приложения Dash (с остальной частью репозитория вы можете ознакомиться на GitHub):
Лично мне нравится Heroku за развертывание прототипов . Вам нужно будет добавить requirements.txt и Procfile. Если вам нужна помощь, вы можете найти подробные руководства здесь и здесь.
Вывод
Эта статья представляет собой (почти) полное руководство о том, как создать хорошее веб-приложение с помощью Python Dash. Это приложение довольно простое, поскольку в нем нет базы данных и функции входа в систему (может быть, материал для следующего руководства?). Здесь я просто хотел продемонстрировать, как вы можете легко превратить свои идеи в прототип, чтобы показать миру. А теперь, когда вы знаете, как это работает, вы можете разработать собственное приложение.
Я надеюсь, что вам понравилось! Не стесняйтесь обращаться ко мне с вопросами и отзывами или просто для того, чтобы поделиться своими интересными проектами.
LinkedIn | Инстаграм | Twitter | GitHub
Эта статья является частью серии Веб-разработка с помощью Python, см. Также:
«Создание и развертывание бота Telegram с краткосрочной и долгосрочной памятью
Создайте чат-бота с нуля, который запоминает и напоминает события с помощью Python pub.towardsai. сеть»
Build A Dashboard In Python – Plotly Dash Step-by-Step Tutorial
Build A Dashboard In Python – Plotly Dash Step-by-Step Tutorial
From my experience here at
STATWORX
, the best way to learn something is by trying it out yourself – with a little help from a friend! In this article, I will focus on giving you a hands-on guide on how to build a dashboard in Python. As framework, we will be using Dash, and the goal is to create a basic dashboard with a dropdown and two reactive graphs:
Developed as an open-source library by Plotly, the Python framework Dash is built on top of Flask, Plotly.js, and React.js. Dash allows the building of interactive web applications in pure Python and is particularly suited for sharing insights gained from data.
For our purposes, a basic understanding of HTML and CSS can be helpful. Nevertheless, I will provide you with external resources and explain every step thoroughly, so you’ll be able to follow the guide.
The source code can be found on
GitHub
.
The project comprises a style sheet called style.css
, sample stock data stockdata2.csv
and the actual Dash application app.py
If you want your dashboard to look like the one above, please download the file
style.css
from our STATWORX GitHub. That is completely optional and won’t affect the functionalities of your app. Our stylesheet is a customized version of the stylesheet used by the
Dash Uber Rides Demo
. Dash will automatically load any .css-file placed in a folder named assets
.
The documentation on external resources in dash can be found
here
.
Feel free to use the same data we did (
stockdata2.csv
), or any pick any data with the following structure:
date |
stock |
value |
change |
2007-01-03 |
MSFT |
23.95070 |
-0.1667 |
2007-01-03 |
IBM |
80.51796 |
1.0691 |
2007-01-03 |
SBUX |
16.14967 |
0.1134 |
df = pd.read_csv(‘data/stockdata2.csv’, index_col=0, parse_dates=True)
df.index = pd.to_datetime(df[‘Date’])
Getting Started – How to start a Dash app
Getting Started – How to start a Dash app
After installing Dash (instructions can be found
here
), we are ready to start with the application. The following statements will load the necessary packages dash
and dash_html_components
. Without any layout defined, the app won’t start. An empty html.Div
will suffice to get the app up and running.
import dash_html_components as html
If you have already worked with the
WSGI
web application framework
Flask
, the next step will be very familiar to you, as Dash uses Flask under the hood.
app = dash.Dash(__name__)
if __name__ == ‘__main__’:
app.run_server(debug=True)
How a .css-files changes the layout of an app
How a .css-files changes the layout of an app
Worth to mention is that the nesting of components is done via the children
attribute.
app.layout = html.Div(children=[
html.Div(className=‘row’, # Define the row element
html.Div(className=‘four columns div-user-controls’), # Define the left element
html.Div(className=‘eight columns div-for-charts bg-grey’) # Define the right element
The first html.Div()
has one child. Another html.Div
named row
, which will contain all our content. The children of row
are four columns div-user-controls
and eight columns div-for-charts bg-grey
.
The style for these div
components come from our style.css
.
Now let’s first add some more information to our app, such as a title and a description. For that, we use the Dash Components H2
to render a headline and P
to generate html paragraphs.
html.H2(‘Dash — STOCK PRICES’),
html.P(»’Visualising time series with Plotly — Dash»’),
html.P(»’Pick one or more stocks from the dropdown below.»’)
Switch to your terminal and run the app with python app.py
.
The basics of an app’s layout
The basics of an app’s layout
Another nice feature of Flask (and hence Dash) is
hot-reloading
. It makes it possible to update our app on the fly without having to restart the app every time we make a change to our code.
Running our app with debug=True
also adds a button to the bottom right of our app, which lets us take a look at error messages, as well a Callback Graph
. We will come back to the Callback Graph
in the last section of the article when we’re done implementing the functionalities of the app.
Charting in Dash – How to display a Plotly-Figure
Charting in Dash – How to display a Plotly-Figure
With the building blocks for our web app in place, we can now define a plotly-graph. The function dcc.Graph()
from dash_core_components
uses the same figure
argument as the plotly package. Dash translates every aspect of a plotly chart to a corresponding key-value pair, which will be used by the underlying JavaScript library Plotly.js.
In the following section, we will need the express version of plotly.py
, as well as the Package Dash Core Components. Both packages are available with the installation of Dash.
import dash_core_components as dcc
import plotly.express as px
Dash Core Components
has a collection of useful and easy-to-use components, which add interactivity and functionalities to your dashboard.
Plotly Express
is the express-version of plotly.py
, which simplifies the creation of a plotly-graph, with the drawback of having fewer functionalities.
To draw a plot on the right side of our app, add a dcc.Graph()
as a child to the html.Div()
named eight columns div-for-charts bg-grey
. The component dcc.Graph()
is used to render any plotly-powered visualization. In this case, it’s figure
will be created by px.line()
from the Python package plotly.express
. As the express version of Plotly has limited native configurations, we are going to change the layout of our figure
with the method update_layout()
. Here, we use rgba(0, 0, 0, 0)
to set the background transparent. Without updating the default background- and paper color, we would have a big white box in the middle of our app. As dcc.Graph()
only renders the figure in the app; we can’t change its appearance once it’s created.
dcc.Graph(id=‘timeseries’,
config={‘displayModeBar’: False},
template=‘plotly_dark’).update_layout(
{‘plot_bgcolor’: ‘rgba(0, 0, 0, 0)’,
‘paper_bgcolor’: ‘rgba(0, 0, 0, 0)’})
After Dash reload the application, you will end up in something like that: A dashboard with a plotted graph:
Another core component is dcc.dropdown()
, which is used – you’ve guessed it – to create a dropdown menu. The available options in the dropdown menu are either given as arguments or supplied by a function.
For our dropdown menu, we need a function that returns a list of dictionaries. The list contains dictionaries with two keys, label
and value
. These dictionaries provide the available options to the dropdown menu. The value of label
is displayed in our app. The value of value
will be exposed for other functions to use, and should not be changed.
If you prefer the full name of a company to be displayed instead of the short name, you can do so by changing the value of the key label
to Microsoft
. For the sake of simplicity, we will use the same value for the keys label
and value
.
Add the following function to your script, before defining the app’s layout.
# Creates a list of dictionaries, which have the keys ‘label’ and ‘value’.
def get_options(list_stocks):
dict_list.append({‘label’: i, ‘value’: i})
With a function that returns the names of stocks in our data in key-value pairs, we can now add dcc.Dropdown()
from the Dash Core Components to our app. Add a html.Div()
as child to the list of children of four columns div-user-controls
, with the argument className=div-for-dropdown
. This html.Div()
has one child, dcc.Dropdown()
.
We want to be able to select multiple stocks at the same time and a selected default value, so our figure is not empty on startup. Set the argument multi=True
and chose a default stock for value
.
html.Div(className=‘div-for-dropdown’,
dcc.Dropdown(id=‘stockselector’,
options=get_options(df[‘stock’].unique()),
value=[df[‘stock’].sort_values()[0]],
style={‘backgroundColor’: ‘#1E1E1E’},
className=‘stockselector’)
style={‘color’: ‘#1E1E1E’})
The id
and options
arguments in dcc.Dropdown()
will be important in the next section. Every other argument can be changed. If you want to try out different styles for the dropdown menu, follow the
link
for a list of different dropdown menus.
How to add interactive functionalities to your app
How to add interactive functionalities to your app
Callbacks add interactivity to your app. They can take inputs, for example, certain stocks selected via a dropdown menu, pass these inputs to a function and pass the return value of the function to another component. We will write a function that returns a figure based on provided stock names. A callback will pass the selected values from the dropdown to the function and return the figure to a dcc.Grapph()
in our app.
At this point, the selected values in the dropdown menu do not change the stocks displayed in our graph. For that to happen, we need to implement a callback. The callback will handle the communication between our dropdown menu 'stockselector'
and our graph 'timeseries'
. We can delete the figure
we have previously created, as we won’t need it anymore.
We want two graphs in our app, so we will add another dcc.Graph()
with a different id
.
-
Remove the
figure
argument fromdcc.Graph(id='timeseries')
-
Add another
dcc.Graph()
withclassName='change'
as child to thehtml.Div()
namedeight columns div-for-charts bg-grey
.
dcc.Graph(id=‘timeseries’, config={‘displayModeBar’: False})
dcc.Graph(id=‘change’, config={‘displayModeBar’: False})
Callbacks add interactivity to your app. They can take Inputs from components, for example certain stocks selected via a dropdown menu, pass these inputs to a function and pass the returned values from the function back to components.
In our implementation, a callback will be triggered when a user selects a stock. The callback uses the value of the selected items in the dropdown menu (Input) and passes these values to our functions update_timeseries()
and update_change()
. The functions will filter the data based on the passed inputs and return a plotly figure from the filtered data. The callback then passes the figure returned from our functions back to the component specified in the output.
A callback is implemented as a decorator for a function. Multiple inputs and outputs are possible, but for now, we will start with a single input and a single output. We need the class dash.dependencies.Input
and dash.dependencies.Output
.
Add the following line to your import statements.
from dash.dependencies import Input, Output
Input()
and Output()
take the id of a component (e.g. in dcc.Graph(id='timeseries')
the components id is 'timeseries'
) and the property of a component as arguments.
@app.callback(Output(‘id of output component’, ‘property of output component’),
[Input(‘id of input component’, ‘property of input component’)])
def arbitrary_function(value_of_first_input):
The property of the input component is passed to the function as value_of_first_input.
The functions return value is passed to the property of the output component.
If we want our stockselector
to display a time series for one or more specific stocks, we need a function. The value
of our input is a list of stocks selected from the dropdown menu stockselector
.
The function draws the traces of a plotly-figure based on the stocks which were passed as arguments and returns a figure
that can be used by dcc.Graph()
. The inputs for our function are given in the order in which they were set in the callback. Names chosen for the function’s arguments do not impact the way values are assigned.
Update the figure time series
:
@app.callback(Output(‘timeseries’, ‘figure’),
[Input(‘stockselector’, ‘value’)])
def update_timeseries(selected_dropdown_value):
»’ Draw traces of the feature ‘value’ based one the currently selected stocks »’
# Draw and append traces for each stock
for stock in selected_dropdown_value:
trace.append(go.Scatter(x=df_sub[df_sub[‘stock’] == stock].index,
y=df_sub[df_sub[‘stock’] == stock][‘value’],
textposition=‘bottom center’))
data = [val for sublist in traces for val in sublist]
colorway=[«#5E0DAC», ‘#FF4F00’, ‘#375CB1’, ‘#FF7400’, ‘#FFF400’, ‘#FF0056’],
paper_bgcolor=‘rgba(0, 0, 0, 0)’,
plot_bgcolor=‘rgba(0, 0, 0, 0)’,
title={‘text’: ‘Stock Prices’, ‘font’: {‘color’: ‘white’}, ‘x’: 0.5},
xaxis={‘range’: [df_sub.index.min(), df_sub.index.max()]},
-
A
trace
will be drawn for each stock. Create an emptylist
for each trace from the plotly figure.
Within the for-loop, a trace for a plotly figure will be drawn with the function go.Scatter()
.
-
Iterate over the stocks currently selected in our dropdown menu, draw a trace, and append that trace to our list from step 1.
Plotly figures are dictionaries with the keys data
and layout
. The value of data
is our flattened list with the traces we have drawn. The layout
is defined with the plotly class go.Layout().
-
Add the trace to our figure
-
Define the layout of our figure
Now we simply repeat the steps above for our second graph. Just change the data for our y-Axis to change
and slightly adjust the layout.
Update the figure change
:
@app.callback(Output(‘change’, ‘figure’),
[Input(‘stockselector’, ‘value’)])
def update_change(selected_dropdown_value):
»’ Draw traces of the feature ‘change’ based one the currently selected stocks »’
# Draw and append traces for each stock
for stock in selected_dropdown_value:
trace.append(go.Scatter(x=df_sub[df_sub[‘stock’] == stock].index,
y=df_sub[df_sub[‘stock’] == stock][‘change’],
textposition=‘bottom center’))
data = [val for sublist in traces for val in sublist]
colorway=[«#5E0DAC», ‘#FF4F00’, ‘#375CB1’, ‘#FF7400’, ‘#FFF400’, ‘#FF0056’],
paper_bgcolor=‘rgba(0, 0, 0, 0)’,
plot_bgcolor=‘rgba(0, 0, 0, 0)’,
title={‘text’: ‘Daily Change’, ‘font’: {‘color’: ‘white’}, ‘x’: 0.5},
xaxis={‘showticklabels’: False, ‘range’: [df_sub.index.min(), df_sub.index.max()]},
Run your app again. You are now able to select one or more stocks from the dropdown. For each selected item, a line plot will be generated in the graph. By default, the dropdown menu has search functionalities, which makes the selection out of many available options an easy task.
Visualize Callbacks – Callback Graph
Visualize Callbacks – Callback Graph
With the callbacks in place and our app completed, let’s take a quick look at our callback graph. If you are running your app with debug=True
, a button will appear in the bottom right corner of the app. Here we have access to a callback graph, which is a visual representation of the callbacks which we have implemented in our code. The graph shows that our components timeseries
and change
display a figure
based on the value of the component stockselector
.
If your callbacks don’t work how you expect them to, especially when working on larger and more complex apps, this tool will come in handy.
Let’s recap the most important building blocks of Dash. Getting the App up and running requires just a couple lines of code. A basic understanding of HTML and CSS is enough to create a simple Dash dashboard. You don’t have to worry about creating interactive charts, Plotly already does that for you. Making your dashboard reactive is done via Callbacks, which are functions with the users‘ interaction as the input.
If you liked this blog, feel free to contact me via
or
. I am curious to know what you think and always happy to answer any questions about data, my journey to data science, or the exciting things we do here at
STATWORX
.
Содержание
- Краткое руководство по Dash — Python веб-фреймворк для создания дэшбордов. Installation + Dash Layout
- Начнем.
- Примечание
- На заметку
- Но есть несколько важных замечаний:
- Многоразовые компоненты
- Немного о таблицах
- Компоненты ядра (Основные компоненты)
- Остались вопросы?
- Summary
- Визуализация данных с помощью Python Dash
- Установка Dash и Plotly
- Требования по использованию Dash
- Создание Dash-приложения
- Создание app.layout
- Компоненты HTML и CSS в Dash
- Основные компоненты Dash
- Создание финального интерфейса визуализации данных с помощью Python Dash
- Заключение
Краткое руководство по Dash — Python веб-фреймворк для создания дэшбордов. Installation + Dash Layout
Сегодня предлагаю погрузиться в один из удобнейших веб-фреймворков в связке c Python под названием Dash. Появился он не так давно, пару лет назад благодаря разработчикам фреймворка plotly. Сам Dash является связкой Flask, React.Js, HTML и CSS.
Выступление Криса Пармера на PLOTCON 2016
Давайте сразу установим фреймворк. Обновленные версии уточняйте тут.
Друзья, если вы действительно хотите разобраться в данном фреймворке, читайте публикации до конца, так как зачастую сначала следуют примеры, а уже после детальный обзор кода. Если вам все равно непонятно — советую читать документацию по Dash на английском языке в оригинале. Также в рунете есть несколько статей, которые объясняют концепции, которые я решил пропустить в данном туториале.
Начнем.
Приложения Dash состоят из двух частей. Первая часть — «layout» описывает то, как выглядит наше приложение. Вторая часть описывает интерактивность приложения, о ней мы поговорим в следующей статье.
Dash предоставляет Python классы для всех визуальных компонентов приложения. Разработчики предоставляют набор компонентов в так называемых dash_core_components и dash_html_components . Но также вы можете построить свой компонент используя JavaScript и React.js.
В dash_core_components содержатся различные динамические формы такие как, например, выпадающие списки, графики и чек-боксы.
В dash_html_components содержатся html конструкции, которыми можно завернуть наши формы. Например Div блоки или теги заголовков H1, H2, и так далее. Разработчики предоставляют нам некую абстракцию от html с помощью словарей Python.
Чтобы начать разбираться, создадим файл app.py , в котором будет содержаться следующее:
И запустим его из текущей директории командой:
$ python app.py
. Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
Видим, что сервер запустился и готов принимать запросы на порт 8050 (у вас может быть другой порт).
Переходим по адресу http://127.0.0.1:8050/
и видим:
Примечание
На заметку
Dash содержит привычную веб разработчика фичу: hot-reloading . Она активируется в тот момент, когда запускается функция app.run_server(debug=True) . Эта фича обновляет ваш браузер всякий раз, когда вы делаете правки в коде и сохраняете результат. Таким образом нет нужды каждый раз перезапускать сервер.
Как мы помним, Dash содержит компонент для каждого тега HTML. Но также он может принимать все аргументы ключевых слов, как и элементы HTML.
Давайте немного изменим наш код:
Обновляем страницу, и видим:
В этом примере мы изменили стили html.Div и html.H1 с помощью свойства style .
html.H1(‘Hello Dash’, style=<‘textAlign’: ‘center’, ‘color’: ‘#7FDBFF’>) отрендерится в приложении Dash как:
Но есть несколько важных замечаний:
Многоразовые компоненты
Продолжая, представим, что нам нужны некоторые элементы, которые будут меняться, например в зависимости от входных данных пользователя нашего приложения. Для этого в Dash предусмотрены так называемые reusable components . Рассмотрим их на примере таблицы, данные для которой будут загружаться из Pandas dataframe.
Немного о таблицах
Давайте вспомним что из себя представляет таблица в HTML.
HTML таблица определяется тэгом table.
Каждая строка таблица определяется тэгом tr. Хедер таблица определяется тэгом th. A ячейки таблицы заполняются с помощью тэга td.
Получается такая структура:
И выглядит она так:
Firstname | Lastname | Age |
---|---|---|
Jill | Smith | 50 |
Eve | Jackson | 94 |
John | Doe | 80 |
Компоненты ядра (Основные компоненты)
Как мы уже сказали ранее, dash_core_components включает в себя высокоуровнвые элементы. Такие, как: выпадающее меню, графики и прочее.
Вы можете ознакомиться с визуальной стороной этих элементов, каждый из которых сопровождается кодом (очень удобно, вселенский респект разрабочикам из Plot.ly) здесь.
Для того, чтобы разработчик, а именно Вы, могли в коде различать все элементы, принято для каждого компонента ядра писать лейбл. Это что-то типа названия нашего элемента. Это не обязательно, но просто облегчит отладку. А пользователю даст возможность быстрее разобраться в вашем интерфейсе. Далее вы поймете о чем я.
Давайте рассмотрим следующий код:
Тут мы видим, что мы создали как обычно один общий Div блок, в котором содержатся наши различные компоненты ядра. Выглядит это как-то так:
Остались вопросы?
Разработчики подготовили очень подробную документацию, прочитать вы ее можете типичной Python командой для каждого класса:
Summary
Ранее нами изученый layout описывает то, как выглядит наше приложение. По сути он содержит древовидную иерархию HTML тэгов и высокоуровневых элементов ядра Dash, которые содержатся в dash_core_components .
В следующей части мы изучим то, как сделать нашу страничку интерактивной. Если вам понравился данный туториал, ставьте плюсик и подписывайтесь на меня.
* Здесь скоро будет ссылка на следующую часть *
Источник
Визуализация данных с помощью Python Dash
Использование интерфейса визуализации данных, также известное как создание дашбордов, является неотъемлемой частью набора навыков аналитиков данных. Дашборды и приложения для работы с данными используются сейчас повсеместно: от представления результатов анализа с помощью ряда визуальных образов до демонстрации ваших приложений машинного обучения.
Если речь идет о данных, значит, это касается и Python. В частности, мы говорим о библиотеке Dash, которая построена на базе одной из самых популярных библиотек для построения графиков — Plotly.
Dash позволяет легко создавать и делиться результатами анализа данных с помощью интерактивных дашбордов, используя только код Python. Нет необходимости изучать HTML, CSS или сложные JavaScript-фреймворки, такие как React.js.
В этом руководстве вы получите представление о том, на что способен Dash, и как интегрировать его в свой рабочий процесс.
Установка Dash и Plotly
Вы можете установить Dash с помощью pip . Также необходимо инсталлировать библиотеку pandas для работы с наборами данных:
Приведенная выше команда также выполняет установку plotly . Plotly известен своими интерактивными графиками, и Plotly и Dash созданы Plotly Software Foundation, поэтому библиотеки довольно хорошо работают вместе.
Требования по использованию Dash
У такого мощного фреймворка, как Dash, есть несколько требований. Во-первых, вы должны знать Plotly Python, поскольку Dash может отображать только интерактивные графики Plotly.
Далее, вам необходимо базовое понимание HTML и CSS. Dash похож на React, но на языке Python. Это шаблонный фреймворк, на котором вы можете создать сайт без JavaScript.
Дашборд содержит множество графики, и пользователю самому решать, как отобразить все на одной странице. Plotly обрабатывает изображения, но аспект компоновки зависит от Dash и его HTML-компонентов.
Создание Dash-приложения
Давайте создадим наше Dash-приложение. После инсталляции импортируем следующие библиотеки:
dash – это глобальная библиотека, содержащая все основные функции. dash_core_components и dash_html_components – это библиотеки, которые устанавливаются с dash по умолчанию. Они включают специфические для Dash фичи и Python-представление HTML-компонентов (тегов). Подробнее о них позже.
Любое приложение Dash запускается с помощью следующей команды:
Вышеприведенный код полностью создает бойлерплейт для чистого веб-сайта. Нам не нужна пустая страница, поэтому давайте заполним ее.
Сначала мы загрузим встроенный датасет из Plotly и создадим простую диаграмму рассеяния:
Затем мы добавляем это изображение в атрибут layout нашего приложения внутри тега div с небольшими текстами:
Теперь мы создаем HTML-теги с помощью библиотеки dash_html_components (html) , а изображение – используя основные компоненты (dcc) library .
За тегом заголовка H1 следует div , содержащий обычный текст, затем сам график с использованием функции Graph библиотеки dcc . Все это находится внутри атрибута children одного тега DIV.
В конце мы также добавляем команду, которая запускает наше приложение в режиме отладки, то есть изменения вступают в силу по мере внесения поправок в скрипт. Вот полный код на данный момент:
Поместите его в скрипт Python и запустите. В терминале вы получите сообщение о том, что необходимо перейти по этой ссылке: http://127.0.0.1:8050/.
В следующих разделах мы подробно расскажем о том, что здесь произошло.
Создание app.layout
Давайте начнем с атрибута layout . Это единственный атрибут, который содержит все ваши HTML-компоненты и изображения. Вы должны передать ему всю вашу графику и HTML-теги в конечном теге DIV.
В зависимости от размера вашего проекта, данный атрибут может стать довольно большим, поэтому я рекомендую создавать все ваши HTML-теги и фигуры в отдельных переменных, а затем передавать их в layout .
Например, вот как будет выглядеть приведенное выше приложение:
Это гораздо аккуратнее и компактнее, и это одна из тех вещей, о которых вы не узнаете в документации Dash. Там куча вложенного кода вместо того, чтобы сделать вышеописанное.
Компоненты HTML и CSS в Dash
Давайте обсудим, как HTML и CSS работают в Dash. Подбиблиотека dash_html_components содержит наиболее распространенные теги HTML, такие как divs, кнопки, текстовые поля, названия, теги заголовков (H1-6) и т. д.
Они реализованы в коде Python под соответствующими именами как представление их HTML-аналогов. Итак, код, подобный приведенному, ниже:
Будет интерпретироваться вашим браузером следующим образом:
Все HTML-теги этой подбиблиотеки содержат следующие основные аргументы:
id : то же, что и атрибут id HTML-тегов
className : то же самое, что и атрибут class тегов HTML
style : такой же, как атрибут style тегов HTML, но принимает только словарь стилей CSS
children : первый аргумент большинства компонентов HTML
Вот пример div с некоторыми кастомизированными настройками:
Аргумент children уникален — он может принимать числа и строки, но чаще всего вы передаете другие компоненты HTML списком, если это тег-контейнер, например такой как div.
Замечание о стилях CSS: большинство атрибутов стиля CSS используют дефисы для разделения слов. Когда вы передаете их в аргумент style Dash , они должны применять camelCase , например backgroundColor вместо background-color .
Я настоятельно рекомендую вам изучить данные HTML-теги, поскольку это единственное, что сохраняет целостность макета (лейаута) вашего приложения. Вот полный список HTML-тегов, поддерживаемых Dash.
Основные компоненты Dash
Другой важной частью Dash являются его основные компоненты. Библиотека dash_core_components содержит несколько других HTML-тегов, но в нее уже встроено немного CSS и JavaScript.
Некоторые примеры включают выпадающие списки, слайдеры, функционалы загрузки и выгрузки, а также компонент для отображения графиков Plotly.
Вот несколько образцов этих компонентов, начиная с выпадающего списка:
Выпадающий список с мультивыбором:
Слайдер с помеченными точками останова:
Существует универсальный атрибут value, который представляет дефолтное значение при первом рендеринге компонента.
Полный список основных компонентов можно посмотреть здесь.
Создание финального интерфейса визуализации данных с помощью Python Dash
В качестве завершающего примера посмотрите на приведенное ниже приложение:
Мы импортируем датасет Diamonds из Seaborn и создаем три графика: диаграмму рассеяния, гистограмму и скрипичную диаграмму. Мы хотим отобразить график рассеяния и гистограмму рядом друг с другом и поместить скрипичную диаграмму прямо под ними в центре.
Для этого мы создаем два div’а, содержащих график рассеяния и гистограмму, left_figure и right_figure . Затем для простоты эти два div помещаем в еще один div — upper_div .
Мы устанавливаем CSS-стиль flex-box для этого div, который размещает фигуры бок о бок.
Затем мы создаем центральный div, содержащий скрипичную диаграмму, и выравниваем его по центру с помощью flex-box и его атрибута justify-content.
Наконец, мы помещаем все в лейаут внутри последнего DIV и запускаем скрипт. Вот конечный результат:
Заключение
Вот краткое описание шагов по созданию базового Dash-приложения:
Создайте приложение с помощью dash.Dash и дайте ему любое название.
Набросайте лейаут своих графиков в дашборде, прежде чем писать код.
Создайте графики, которые войдут в ваш дашборд
Создайте шаблонный лейаут с помощью HTML-компонентов Dash
Добавьте свои изображеня в соответствующие контейнеры
Наконец, добавьте все HTML-компоненты к атрибуту лейаута
Несмотря на то, что мы рассмотрели многие базовые аспекты, такие как HTML, основные компоненты и лейаут приложения, это лишь поверхностное знакомство с возможностями Dash.
Я показал вам множество примеров интерактивных HTML-компонентов, но не рассказал, как интегрировать их в ваше приложение. Как вы можете обновлять графики на основе вводимых пользователем данных, таких как слайдеры, текст или что-то подобное?
Вот здесь-то и приходят на помощь коллбеки. Это очень мощная и основная фича Dash. Чтобы использовать коллбеки, вы определяете в Dash функции, которые выстреливают при изменении компонента пользователем, и функция модифицирует новый компонент на основе этого события.
Dash посвящает большой раздел в документации только для объяснения коллбеков, поскольку поначалу в них трудно разобраться. Я предлагаю вам обратиться к этой теме на следующем этапе.
Загляните в галерею примеров, где вы сможете увидеть и насладиться некоторыми очень крутыми проектами, созданными с помощью Dash. Самое приятное, что многие из них с открытым исходным кодом, а это значит, что вы можете многое для себя почерпнуть и вдохновиться на новые идеи.
Спасибо за прочтение!
В заключение приглашаем на открытое занятие «Работа с Power BI. Построение дашборда. Настройка и взаимодействие визуальных элементов». На уроке загрузим данные в Power BI Desktop из источника, построим небольшой дашборд, посмотрим на назначение и варианты настройки базовых визуальных элементов. Записаться можно по ссылке.
Источник
Dash — библиотека для языка Python с открытым исходным кодом, предназначенная для создания реактивных веб-приложений. Она была загружена на GitHub два года назад в тестовом режиме. Команда разработчиков Dash решила оставить этот прототип в сети, однако продолжила вести работу над проектом уже вне платформы GitHub. Благодаря обратной связи от банков и лабораторий, а также от команд, работающих с анализом данных, разработчики определили курс развития библиотеки. Сегодня уже представлена первая публичная версия Dash, которая подходит как для корпоративных клиентов, так для клиентов премиум-класса продукции Plotly. Библиотека может быть использована как с Plotly, так и самостоятельно.
В настоящее время Dash можно загрузить, используя диспетчер пакетов Python, с помощью команды pip install dash
. Dash распространяется с открытым исходным кодом и под лицензией MIT. На официальном сайте вы сможете ознакомиться с руководством по библиотеке, и на GitHub вы найдёте исходный код.
Dash — библиотека пользовательского интерфейса для создания аналитических веб-приложений. Она будет полезна для тех, кто использует Python для анализа и исследования данных, визуализации, моделирования и отчётности.
Dash значительно упрощает создание GUI (графических пользовательских интерфейсов) для анализа данных. Вот пример приложения на Dash из 43 строк кода, который связывает выпадающее меню с графиком D3.js. Когда пользователь выбирает значение в выпадающем списке, код динамически экспортирует данные из Google Finance в Pandas DataFrame:
Код Dash является декларативным и реактивным, что упрощает создание сложных приложений, содержащих множество интерактивных элементов. Вот пример с 5 входными данными, 3 — выходными и с перекрёстной фильтрацией. Это приложение было написано на Python, и в нём всего лишь 160 строк кода:
Приложение на Dash с несколькими входными и выходными данным.
Для каждого элемента приложения можно задать собственные параметры размера, расположения, цвета и шрифта. Приложения на Dash создаются и публикуются в Сети, поэтому к ним можно применить всё, на что способен CSS. Ниже иллюстрируется пример тонко настраиваемого интерактивного приложения отчётности на Dash, выполненного в стиле отчёта финансовой организации Goldman Sachs.
Тонко настраиваемое приложение Dash, созданное в стиле отчёта финансовой организации Goldman Sachs.
Вам не нужно писать какой-либо код на JavaScript или HTML, когда ваше приложение на Dash запущено в веб-браузере. Dash предоставляет богатый набор интерактивных веб-компонентов.
import dash_core_components as dcc
dcc.Slider(value=4, min=-10, max=20, step=0.5,
labels={-5: '-5 Degrees', 0: '0', 10: '10 Degrees'})
Пример простого ползунка на Dash
Dash предоставляет простой реактивный декоратор для привязки вашего кода анализа данных к пользовательскому интерфейсу Dash.
@dash_app.callback(Output('graph-id', 'figure'),
[Input('slider-id', 'value')])
def your_data_analysis_function(new_slider_value):
new_figure = your_compute_figure_function(new_slider_value)
return new_figure
Когда изменяется входной элемент (например, при выборе элемента в выпадающем списке или при передвижении ползунка), декоратор Dash предоставляет вашему коду Python новое входное значение.
Ваша функция Python может выполнять различные действия с новым входным значением: может фильтровать объект DataFrame
библиотеки Pandas, выполнять SQL-запрос, запускать симуляцию, выполнять вычисления или запускать тестирование. Dash рассчитывает, что ваша функция вернёт новое свойство для какого-нибудь элемента пользовательского интерфейса, будь то новый график, новая таблица или новый текст.
В качестве примера ниже представлено приложение на Dash, которое обновляет текстовый элемент при взаимодействии с графиком. Код приложения фильтрует данные в Pandas DataFrame
на основе выбранной точки:
Приложение ниже отображает метаинформацию о лекарственных веществах при наведении курсора на точки в графике. Код приложения также добавляет строки в таблицу, когда появляются новые компоненты в выпадающем списке.
Благодаря этим двум разделениям между компонентами Python и реактивными функциональными декораторами, Dash разграничивает все технологии и протоколы, необходимые для создания интерактивного веб-приложения. Dash достаточно прост, чтобы привязать пользовательский интерфейс к коду Python за один вечер.
Архитектура
Flask и React.js
Приложения на Dash — веб-серверы, которые запускают Flask и связывают пакеты JSON через HTTP-запросы. Интерфейс Dash формирует компоненты, используя React.js.
Flask — великолепный фреймворк, который широко используется сообществом разработчиков Python во многих проектах. Основной экземпляр Flask и все его настраиваемые свойства доступны разработчикам приложений на Dash. Продвинутые разработчики могут расширить возможности приложений с помощью богатой коллекции плагинов Flask.
React.js также великолепен, например, мы переписали всю нашу веб-платформу и наш онлайн-редактор диаграмм с помощью React. Но есть кое-что, что действительно радует насчёт React — активный и талантливый состав сообщества разработчиков, который опубликовал тысячи высококачественных компонентов, начиная с выпадающих списков и слайдеров, заканчивая календарями и интерактивными таблицами. И всё это публикуется с открытым исходным кодом!
Dash использует мощь Flask и React, подстраивая их под работу с Python для специалистов по анализу и обработке данных, которые могут не быть экспертами в области веб-разработки.
От React.js к компонентам Python
Компоненты Dash — это классы Python, которые кодируют свойства и значения конкретного компонента React и упорядочиваются как JSON. Dash предоставляет набор инструментов для лёгкой упаковки компонентов React в вид компонентов, которые могут быть использованы в Dash. Этот набор инструментов использует динамическое программирования для автоматического создания классов Python из аннотированного свойства React — propTypes
. На выходе классы Python, которые представляют компоненты Dash, являются удобными для пользователя, так как они имеют автоматическую проверку аргументов, строк документации и прочее.
Вот пример динамически сгенерированной проверки ошибочного аргумента:
>>> import dash_core_components as dcc
>>> dcc.Dropdown(valu=3)
Ошибка: неизвестный ключевой аргумент `valu`
Допустимые аргументы: id, className, disabled, multi, options, placeholder, value
Пример динамически создаваемых строк документации:
>>> help(dcc.Dropdown)
class Dropdown(dash.development.base_component.Component)
| Компонент выпадающего списка.
| Компонент выпадающего списка служит для выбора одного или более
| элементов.
| значения и названия элементов выпадающего списка определяются в `options`
| свойство и выбранный элемент(ы) определяются свойством `value`.
|
| используйте выпадающий список, только если у вас много вариантов выбора (больше 5), или
| когда вы ограничены пространством. В противном случае вы можете использовать переключатели или чекбоксы,
| Которые покажут сразу все элементы пользователю.
|
| Аргументы ключевых слов:
| - id (строка; необязательный)
| - className (строка; необязательный)
| - disabled (логический тип; необязательный): если true, выбор блокируется
| - multi (логический тип; необязательный): если true, пользователь может выбрать несколько значений
| - options (список; необязательный)
| - placeholder (строка; необязательный): серый текст по умолчанию, если ничего не выбрано
| - value (строка | список; необязательный): значение поля ввода. Если `multi` false (по умолчанию),
| то value — строка, соответствующая своим значениям,
| указанным в свойстве `options`. Если `multi` — true, то
| можно выбрать сразу несколько значений, а `value` —
| массив элементов со значениями, соответствующими в свойстве
| `options`.
|
| Доступные события: 'change
Полный набор HTML-тегов (наподобие div
, img
, table
) также обрабатывается с помощью React, а их классы Python доступны через библиотеку dash_html_component
. Основной набор интерактивных компонентов, таких как Dropdown
, Graph
, Slider
, будет поддерживаться командой Dash через dash_core_components
. Обе библиотеки используют стандартный набор инструментальных средств React-to-Dash с открытым исходным кодом, который вы могли бы использовать при необходимости написания своей собственной библиотеки компонентов.
Ваше приложение автоматически не привязывается к библиотеке компонентов Dash. Библиотека компонентов импортируется отдельно от основной библиотеки Dash. С помощью набора инструментальных средств React-to-Dash можно легко записать или перенести компонент React.js в класс Python, который можно использовать в приложении Dash. На официальном сайте вы найдёте руководство по созданию собственных компонентов или можете попросить команду разработчиков Dash написать их для вас.
Многопользовательские приложения
Свойства приложения на Dash хранятся в интерфейсе (в браузере). Это позволяет использовать приложения, написанные с использованием Dash, в многопользовательском режиме: может быть открыто несколько независимых друг от друга сессий, в которых действия одних пользователей не будут влиять на данные других пользователей. Код приложения на Dash является функциональным: он может считывать значения из глобальных свойств Python, но не может вносить в них изменения. Этот функциональный подход можно легко обосновать и протестировать — это просто входные и выходные данные без каких-либо побочных эффектов или свойств.
CSS и стили
CSS и стили по умолчанию хранятся вне базовой библиотеки, чтобы сохранить принцип модульности и независимого управления версиями и чтобы подтолкнуть разработчиков Dash-приложений настраивать вид своих приложений. Команда Dash разместила руководство по основным стилям.
Визуализация данных
Библиотека Dash поставляется с компонентом Graph, который отвечает за отображение диаграмм с помощью Plotly.js. Библиотека Plotly.js отлично подходит к Dash (отличное дополнение), так как она декларативна и имеет открытый исходный код. Кроме того, она поддерживает полный спектр научных, финансовых и деловых диаграмм. Она создана на основе D3.js (для диаграмм типографического качества и экспорта векторных изображений) и WebGL (для высокопроизводительной визуализации).
В библиотеке Dash элемент Graph использует тот же синтаксис, что и библиотека Plotly.py с открытым исходным кодом, что даёт вам возможность легко переключаться между ними. Компонент Graph подключается к системе событий Plotly.js, позволяя авторам писать приложения, которые реагируют на наведение курсора, щелчки и выбор определённых точек на графиках Plotly.
Репозитории с открытым исходным кодом
- бэкенд библиотеки Dash;
- фронтенд библиотеки Dash;
- библиотека основных компонентов Dash;
- библиотека HTML-компонентов Dash;
- набор инструментальных средств React-to-Dash;
- документация и руководство по Dash;
- Plotly.js —JavaScript- библиотека, используемая Dash.
Прототипирование
Dash — это новая библиотека в среде Python, однако концепции и идеи, на которых строится Dash, существуют в течение десятилетий на разных языках и в разных приложениях.
Если вы разбираетесь в Excel, значит, вам будет проще разобраться и в Dash. Ведь они оба используют «реактивную» модель программирования. В Excel ячейки с выходными данными обновляются автоматически при изменении параметров ячеек с входными данными. Любая ячейка может быть входной или выходной или и тем, и другим. В ячейках с входными данными нет информации о том, какие ячейки с выходными данными зависят от них, что упрощает добавление новых ячеек с выходными данными или позволяет связать несколько ячеек. Вот пример Excel-приложения:
Можно провести аналогию для Dash. Вместо ячеек у нас есть богатый спектр веб-компонентов, таких как ползунки, поля ввода, выпадающие списки и графики. Вместо написания сценария Excel или VBA мы пишем код Python. Ниже представлено то же самое приложение, но в этот раз оно написано на Dash:
app.layout = html.Div([
html.Label('Hours per Day'),
dcc.Slider(id='hours', value=5, min=0, max=24, step=1),
html.Label('Rate'),
dcc.Input(id='rate', value=2, type='number'),
html.Label('Amount per Day'),
html.Div(id='amount'),
html.Label('Amount per Week'),
html.Div(id='amount-per-week')
])
@app.callback(Output('amount', 'children'),
[Input('hours', 'value'), Input('rate', 'value')])
def compute_amount(hours, rate):
return float(hours) * float(rate)
@app.callback(Output('amount-per-week', 'children'),
[Input('amount', 'children')])
def compute_amount(amount):
return float(amount) * 7
Некоторым разработчикам нравится этот пример, потому что Excel по-прежнему занимает доминирующее положение даже в технических вычислениях и в финансовой математике. Я не думаю, что доминирующее положение Excel — это технический вопрос. В конце концов, есть легионы программистов, которые изучили нюансы Excel, VBA и даже SQL.
Более того, таблицы Excel легче распространять, чем программы на Python, а ячейки Excel легче редактировать, чем аргументы командной строки.
Тем не менее, моделирование в Excel имеет известные ограничения: эти таблицы часто становятся слишком большими или уязвимыми, чтобы переводить их на производственный уровень, проводить экспертную оценку или тестировать и поддерживать. Вам ведь знаком случай со знаменитой опечаткой в 2013 году?
Надеемся, что Dash сделает использование Python в проектах по обработке данных проще. Благодаря одним и тем же функциональным и реактивным принципам, можно так же легко написать приложение на Dash, как написать аналитическую таблицу. Это, безусловно, более мощный и презентабельный инструмент.
Фреймворк Shiny
Если вы программируете на R, вам повезло. Shiny — это реактивный фреймворк для создания веб-приложений на чистом R, и это отлично! Вы даже можете создавать интерактивные графики с библиотекой Shiny или Plotly для R. Dash и Shiny похожи, но Dash не стремится быть копией Shiny, так как философии Python и R достаточно различаются, что приводит к необходимости использования разного синтаксиса.
Интерактивное веб-приложение, созданное с помощью Shiny на языке R.
Структурирование данных с MATLAB
Если вы программируете на MATLAB, то вам, возможно, знакома GUIDE — библиотека пользовательского интерфейса для MATLAB. Компания Mathworks была одной из новаторов в области технических вычислений. GUIDE была написана в далёком 2004 году.
Приложение, созданное с помощью библиотеки GUIDE на MATLAB.
Если ваши данные структурированы в базе данных, вы могли бы использовать Tableau или любой другой BI-инструмент. Tableau — восхитительный инструмент. Компания установила новый вектор развития в своей отрасли, согласно которому, у конечного пользователя должна быть автономия, чтобы он мог иметь возможность исследовать данные внутри своей организации. Компания также помогла сделать популярнее концепции детализации данных и перекрёстной фильтрации.
Перекрёстная фильтрация в Tableau.
Dash также служит дополнением к BI-инструментам, наподобие вышеупомянутых. Они отлично подходят для структурирования данных. Но когда дело доходит до преобразования данных и аналитики, превзойти размах и гибкость языков программирования и сообществ, вроде Python, становится труднее. Dash абстрагируется от множества сложностей в создании пользовательских интерфейсов, позволяя вам сделать это красиво для вашей аналитической базы данных.
Виджеты Jupyter
Наконец, пришло время рассказать о виджетах Jupyter. Они обеспечивают действительно приятный фреймворк внутри интерфейса Notebook. Вы можете добавлять ползунки к вашим графикам в Jupyter Notebook.
Виджеты в Dash похожи на виджеты Jupyter. В Jupyter Notebooks есть возможность добавлять виджеты непосредственно рядом с кодом. В Dash элементы управления хранятся отдельно от вашего кода. Dash больше нацелена на приложения для распространения, чем на распространяемый код и документацию. Вы всегда можете смешивать и сопоставлять инструменты, создавая свои приложения на Dash в среде Jupyter Notebook.
Команде разработчиков Dash также очень нравится проект nteract, который действительно снижает порог вхождения в Python и Jupyter Notebook, позволяя упаковать Jupyter Notebook в виде настольного приложения.
Лицензирование и бизнес-модель с открытым исходным кодом
Стартап поддерживает библиотеки с открытым исходным кодом для Python, R и MATLAB, которые взаимодействуют с plotly.js. Компания также поддерживает веб-приложение для создания диаграмм и подключения их к базам данных (стыковочные библиотеки также распространяются с открытым исходным кодом).
Если вы используете локальную версию с открытым исходным кодом, в таком случае ограничений нет. Вы можете управлять развёртыванием Dash-приложений самостоятельно через платформы вроде Heroku или Digital Ocean.
Если вы ищите вдохновение для создания своих пользовательских интерфейсов в области технических вычислений, рекомендуем прочитать статью Брета Виктора
Вам также может понравиться проект Explorable Explanations, который специализируется на интерактивном обучении.
Перевод статьи «Create Reactive Web Apps in pure Python»
In this tutorial, you’ll learn how to create Python interactive dashboards using plotly Dash, with an example.
Web-based dashboards are an efficient way to display and share information with others. But it often involves a complicated process that only expert web developers can achieve. As Python programmers in data science, how can we build an interactive web application with data visualizations?
Plotly Dash
is the go-to library. It empowers us to build beautiful looking, interactive, and easy to share dashboards, all in Python.
Following this Python Dash tutorial, you’ll learn:
- What is Dash
- How to build the Dash app layout with data visualization
- How to add interactive features (callbacks)
- How to run and display the dashboard
So if you want to build your first interactive dashboard with Python Dash, this tutorial will walk you through an example step-by-step.
Let’s get started!
Editor’s Note: This tutorial is updated in April 2022 to include the new features in Dash 2.0.
Further learning: to learn more details and depth about Dash, please take our video course: Python Interactive Dashboards with Plotly Dash. It includes step-by-step explanations, more advanced functions, all with real-world dataset examples.
To follow this Python interactive dashboard in Dash tutorial, you need to know Python, including basic knowledge of pandas
. If you need help, please check out the below resources:
- Python basics: FREE Python crash course
- Python
pandas
: Python for Data Analysis with projects course. This course teachespandas
, which is necessary to transform the dataset into a dashboard, and much more!
Table Of Contents
- What is Dash?
- Step #1: Exploring the dataset
- Step #2: Setting up the Python environment
- Step #3: Preparing to build the Dash app
- Step #4: Building the layout of the dashboard
- Step #5: Adding interactivity to the dashboard
- Step #6: Running the dashboard
What is Dash?
Dash is a free Python library built by the same company that created the plotly
graphing library. With Dash, you can develop web-based, customizable, interactive dashboards, all in Python, without writing HTML or JavaScript.
Each Dash app has two main parts:
- layout: determines what the Dash app looks like
- callback functions: the function that connects the Dash components and defines their interactive features
We’ll build both parts in this tutorial. Now let’s go through our example to make an interactive data visualization using Dash.
Step #1: Exploring the dataset
Before building the Dash app, we need to explore the dataset. We recommend doing this in JupyterLab/Notebook. Since it has an interactive interface, we can easily code and examine the outputs.
First, we’ll import two libraries (please install them if you haven’t):
pandas
: for loading and manipulating datasetsplotly.express
: for generating data visualizations
Dash is built on top of plotly, so it’s easy to put plotly figures into Dash apps. This is why we are using plotly, instead of other Python data visualization libraries
In this tutorial, we’ll use the Avocado Prices dataset to build our example dashboard. So let’s load it and take a look at its summary.
As you can see, the dataset contains information about avocados.
<class 'pandas.core.frame.DataFrame'> RangeIndex: 30021 entries, 0 to 30020 Data columns (total 13 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 date 30021 non-null object 1 average_price 30021 non-null float64 2 total_volume 30021 non-null float64 3 4046 30021 non-null float64 4 4225 30021 non-null float64 5 4770 30021 non-null float64 6 total_bags 30021 non-null float64 7 small_bags 30021 non-null float64 8 large_bags 30021 non-null float64 9 xlarge_bags 30021 non-null float64 10 type 30021 non-null object 11 year 30021 non-null int64 12 geography 30021 non-null object dtypes: float64(9), int64(1), object(3) memory usage: 3.0+ MB
Now suppose we want to present the average prices of different types of avocados for various geographies across time, i.e., we want to focus on presenting the information of the columns date
, average_price
, type
, and geography
.
Let’s explore these columns more. What are the different type
and geography
of avocados? Let’s take a look at the categories using the value_counts
method. This will show us the unique categories for these variables.
From the results below, you can see that there are two categories of type
, and many different categories for geography
.
conventional 15012 organic 15009 Name: type, dtype: int64
Phoenix/Tucson 556 Northeast 556 Las Vegas 556 Sacramento 556 Tampa 556 Spokane 556 Southeast 556 New York 556 Raleigh/Greensboro 556 Syracuse 556 Plains 556 California 556 Orlando 556 Albany 556 Boise 556 Boston 556 Houston 556 West 556 Portland 556 Harrisburg/Scranton 556 Cincinnati/Dayton 556 Miami/Ft. Lauderdale 556 Dallas/Ft. Worth 556 Hartford/Springfield 556 Great Lakes 556 Louisville 556 Philadelphia 556 Pittsburgh 556 Baltimore/Washington 556 Roanoke 556 Jacksonville 556 Midsouth 556 Chicago 556 San Francisco 556 South Central 556 San Diego 556 Detroit 556 Grand Rapids 556 Nashville 556 Charlotte 556 Seattle 556 Los Angeles 556 Northern New England 556 Indianapolis 556 Buffalo/Rochester 556 Total U.S. 556 Richmond/Norfolk 556 New Orleans/Mobile 556 Denver 556 St. Louis 556 Atlanta 556 South Carolina 556 Columbus 556 West Tex/New Mexico 553 Name: geography, dtype: int64
Since there are only two avocados types, we can plot their average_price
time series on the same line chart. Let’s try creating such a figure when geography
is ‘Los Angeles’.
Further Learning: If you are not familiar with plotly, please look at our tutorial, Plotly Python Tutorial: How to create interactive graphs.
This is a nice chart, but it’s only for one geography
of ‘Los Angeles’.
How can we make it easy for users to explore this information from different geography
?
If we have a dropdown with geography
options, the users would be able to choose among them. Then according to the geography
selected by the users, we can display the above line plot to them for that specific geography
.
This is something we can do easily with Dash!
It’s time to use Dash.
Step #2: Setting up the Python environment
After exploring the dataset in Jupyter Notebook, we recommend using one of the Python editors to implement Dash apps. This is because when working on Dash apps, we want to focus on building and running the dashboards as a whole script. So it’s easier to test in Python editors such as PyCharm.
We’re using the PyCharm Editor – Community Edition. It’s free and has many useful features for writing Python code. However, if you still prefer Jupyter Notebook, you can try out the library jupyter-dash, which will not be covered in this tutorial.
It’s also necessary to use the pip install dash
command in your terminal to install Dash before using it.
Step #3: Preparing to build the Dash app
We can head over to the Python editor such as PyCharm to start writing the Dash app.
The code snippets below need to be combined and run as a single Python script. We are breaking them down into pieces so that it’s easier to explain. You can either type them into your Python file or copy and paste the complete version, which will be provided in the last step of this tutorial.
First, we need to import the libraries. The necessary ones for our dashboard are:
dash
: the Dash library, which includes:Dash
: class Dash
html
(Dash HTML Components module): for building the layout, which contains components for every HTML tag, such as the H1 headingdcc
(Dash Core Components module): for building the layout, which contains various higher-level components such as dropdown and graphInput
,Output
: for defining callback functions
pandas
: loading and manipulating the dataplotly.express
: creating figures
Then we can load the dataset as a pandas
DataFrame, which is the same as earlier. Please make sure you’ve saved this Python script and the dataset avocado-updated-2020.csv
in the same directory to avoid setting the path in the read_csv
function.
We’ll also create a Dash app object called app
. This app
is what we’ll be focusing on for the rest of the tutorial.
Step #4: Building the layout of the dashboard
The app-building process always starts from the layout. So first, we need to design the look of the dashboard.
The layout has the structure of a tree of components. And we use the keyword layout
of the app
to specify its layout. Then, using the two modules: html
and dcc
, we can display three components on our dashboard, from top to down:
- an H1 heading (
html.H1
) as the dashboard’s title. We specify its children property to be the text ‘Avocado Prices Dashboard’ - a dropdown menu (
geo_dropdown
, which is adcc.Dropdown
) based on thegeography
We’ve built it as a variable outside and then referenced it within thelayout
:
–options
: this property specifies the options of unique geographies the dropdown has
–value:
this property is the selected geography when we first launch the app. We made it as ‘New York’ - a graph (
dcc.Graph
) with id ‘price-graph’
Below is the code to set up the layout.
As you might have noticed, we are using an html.Div
component to hold our three Dash components. The html.Div
is a container component, which is always used when we have multiple Dash components in the layout. We put the other Dash components as a list inside its children
property.
After setting up the dashboard’s look, it’s time to add a callback function to make it interactive.
Step #5: Adding interactivity to the dashboard
The callback functions are Python functions. They get automatically called by Dash whenever their inputs change. As a result, the functions run and update their outputs.
The two main sections of the callback function are:
- decorator, which starts with
@app.callback
- function itself, which begins with
def
Below is the code of our callback function to make the plotly figure dependent on the dropdown.
Within the decorator @app.callback
, we specify the Output
and the Input
objects of the callback function. They are both the properties of Dash components.
In our example, the output is the figure
property of the Dash component with id = ‘price-graph’, which is the dcc.Graph
component set in the layout
. While the input is the value
property of the Dash component with the variable name geo_dropdown
, which is the dcc.Dropdown
component set in the layout
. So you’ve seen two ways of specifying components in the callback function:
- pass the ID to
component_id
- pass the variable name directly to
component_id
, in which case Dash autogenerates IDs for the component
After specifying them, we use them within the function below. Within the parenthesis after the def update_graph
, we name the input as selected_geography
. This corresponds to the Input(component_id=geo_dropdown, component_property='value')
. Then within the body of the function, we ask the function to:
- generate a filtered dataset
filtered_avocado
based onselected_geography
- create a plotly line figure called
line_fig
based on this filtered dataset
The function returns this line_fig
as the output, which corresponds to Output(component_id='price-graph', component_property='figure')
.
Here is an example. When the user selects ‘Los Angeles’ in the dropdown component, its value
property will become ‘Los Angeles’, which means the input of the function selected_geography='Los Angeles'
. This change will trigger the callback function, and update the output, as the line figure is only for Los Angeles.
That’s all the work needed for the callback function!
We are ready to run the dashboard.
Step #6: Running the dashboard
By default, the Dash app runs on our local computers. To complete the script, we need to add code to run the server. We can add these two lines of code after the callback function.
And that’s it!
As mentioned earlier, we need to run all the code as a whole script. So if you haven’t, you can copy the complete script below and save it into your Python editor:
So we can name this Python script avocado_example
, and save it under the same directory as the dataset avocado-updated-2020.csv
. Then we can go to the terminal to run it by typing in the command python avocado_example.py
.
After running successfully, you should see the below messages in the terminal window.
Dash is running on http://127.0.0.1:8050/
* Serving Flask app "avocado_example" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
Remember that Dash creates web applications? So this URL http://127.0.0.1:8050/
is the default address to access the app. You can go to it and see your first Python interactive dashboard opening in the browser!
This is what it should look like:
If you haven’t got the chance to run your app, look here. We have deployed this app on Heroku so that you can interact with it as a user. Try to select different geographies within the dropdown and see the updated graph.
In this tutorial, you’ve successfully created your first Python interactive dashboard with plotly Dash!
Again, to learn about how to:
- set up more Dash components such as range slider, radio items, datatable
- customize the look of the dashboards
- create a grid layout dashboard
- more dynamic interactive features
Please take our video-format course: Python Interactive Dashboards with Plotly Dash. You’ll also get an overview of HTML and CSS within the course to better understand Dash.
Leave a comment for any questions you may have or anything else.