Plotly, Python, Tutorial

Using Dash, from Plotly, to build interactive Dashboards from scratch – Part 1

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.

Setting up a Python environment

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

Plotly Dash App template

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.

Processing data with callbacks

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

layout_inputs = html.Div([
    html.H3("Inputs"),
    html.Div(children=[
        html.Div(children=[
            html.Label("Mean"),
            dcc.Input(id="input-mean", type="number", className="form-control", value="0")
        ]),
    ], className="row"),
    html.Div(children=[
        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

layout_visualization = html.Div([
    html.H3("Visualization"),
    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

@app.callback(Output('output-data', component_property='figure'),
              [Input('input-mean', 'value'),
              Input('input-stdv', 'value'),])
def update_visualization(mean, stdv):
    time_series = np.random.normal(mean, stdv, 1000)
    chart_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.

Leave a Reply

Your email address will not be published. Required fields are marked *