Using Plotly Dash to build interactive Dashboards from scratch
By: Cristiano Aguiar
Tags: Data Visualization, Data Exploration, Plotly

In this article I am going to explain my workflow to build a dashboard to display results from an Exploratory Data Analysis, for example. The goal is to have a template of a Plotly Dash app to make it quick and easy to experiment with your dataset. First, let’s use pyenv and pyenv-virtualenv to handle Python versions and virtual environments. To install them take a look in their repos here and here After having these tools up and running, go to your terminal to install a Python version:

pyenv install 3.6.1

Now, create a new virtual environment from it

pyenv virtualenv 3.6.1 dashboard

This will install Python 3.6.1 and create a virtual environment called dashboard. Now, activate this environment by running:

pyenv activate dashboard

Now, let’s install the needed packages:

pip install dash dash-table pandas

After using Plotly Dash for some projects, I realized that it is easy build a messy and hard to maintain app if you don’t split the code in some files. I usually follow a structure in each project that allows me to navigate and build up new features easily.

First we create a new main file, called app.py. This is the python file to be run to start the server. The content of this file is:

from server import app

from layouts.main import main_layout # Include Bootstrap CSS app.css.append_css({"external_url": "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"}) # Include layout app.layout = main_layout # Include callbacks (Needs to be assigned after setting layout up)

from callbacks.main import * # Initializing app

if __name__ == '__main__':

app.run_server(debug=True)

Next, we need a server file, which is going to create the Dash App server:

import dash app = dash.Dash()

This one is straightforward, just creating the Flask Dash App instance. If you run this app, It won’t work since you need at least a base layout to start. Let’s create this basic layout, both the main.py and the inner layouts. At this point it is worth mention that the Bootstrap classes are pulled up in this line on the app.py:

app.css.append_css({"external_url": "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"})

This mean that we can use their style, as you’re going to see later. The main layout is composed by a title and two columns, one with the inputs and another one with the visualization. It is empty, for now, but the /layouts/main.py looks like this:

import dash_html_components as html

import dash_core_components as dcc

from layouts.inputs import layout_inputs

from layouts.visualization import layout_visualization main_layout = html.Div([

html.Div([

html.Div([

html.H1("Dashboard")

]), ], className="row"),

html.Div([

html.Div([

layout_inputs

], className="col-4"),

html.Div([

layout_visualization

], className="col-8"),

], className="row"),

], className="container")

In this article, I am going to add a random dataset to display a graph, in the next part of this walkthrough we are going to use a real dataset to explore. First let’s add our inputs and visualization layouts, right now, they are just placeholders.

inputs.py:

import dash_html_components as html layout_inputs = html.Div([

html.H3("Inputs")

])

visualization.py:

import dash_html_components as html layout_visualization = html.Div([

html.H3("Visualization")

])

Even though we don’t have any callback, we can run this code right now and head to http://127.0.0.1:8050/ in the browser and see how it is at this moment. It will look very simple now. First, let’s build a simple mean and standard deviation inputs to generate a random time series from a Normal Distribution and plot it. We need to update our inputs.py to include inputs and labels, the file now becomes

import dash_html_components as html

import dash_core_components as dcc # Input layouts

layout_inputs = html.Div([

html.H3("Inputs"),

html.Div(children=[

# Average

html.Div(children=[

html.Label("Mean"),

dcc.Input(id="input-mean", type="number", className="form-control", value=0)

]),

], className="row"),

html.Div(children=[

# Standard Deviation

html.Div(children=[

html.Label("Standard Deviation"),

dcc.Input(id="input-stdv", type="number", className="form-control", value=1)

]),

], className="row"),

])

The layout for visualization needs to include the output for chart. Then, visualization.py becomes:

import dash_html_components as html

import dash_core_components as dcc # Visualization Layout

layout_visualization = html.Div([

html.H3("Visualization"),

# Element to output plotly chart

dcc.Graph(id='output-data')

])

Finally, we just need to add our update function on the callback modules. First the visualization.py file in the callbacks folder become:

import numpy as np

from server import app

from dash.dependencies import Input, Output

import plotly.graph_objs as go def _generate_chart(series):

# Create a trace

trace = go.Scatter(

y = series

) data = [trace] fig = {

'data': data

}

return fig

[Input('input-mean', 'value'),

Input('input-stdv', 'value'),])

def update_visualization(mean, stdv):

# Generates a random sample from a Normal Distribution

time_series = np.random.normal(mean, stdv, 1000)

# Generates a plotly chart

chart_layout = _generate_chart(time_series)

return chart_layout @app .callback(Output('output-data', component_property='figure'),[Input('input-mean', 'value'),Input('input-stdv', 'value'),])def update_visualization(mean, stdv):# Generates a random sample from a Normal Distributiontime_series = np.random.normal(mean, stdv, 1000)# Generates a plotly chartchart_layout = _generate_chart(time_series)return chart_layout

This module will use the callback decorator from Dash using our graph output layout defined above. As inputs, we include our mean and standard deviation. The logic here is plain simple, just generating a scatter plot using the Plotly API with a random number generator with normal distribution from numpy. We just need to load this module in the main.py inside the callbacks folder.

from callbacks.visualization import *

That’s it! The callback will listen to any change in the inputs, call the generator again and plot the chart. Run the server again and you can see interact with the page in your browser.

This is the first part of this Dashboard series with Plotly Dash. In the next post I’ll try to improve the data exploration using another dataset and different visualizations. The code for this post can be found here.