Introduction to Python Dash Framework for Dashboard Generation

Dashboards play a crucial role in conveying useful and actionable information from collected data regardless of context. As with economically feasible sensors, improved computation, and storage facility, and IoT framework, it has become easier to collect an enormous amount of data from a variety of contexts (e.g. military, health-care, education). However, finding insights out of collected data still remains a challenge. This post offers an introduction to python dash a framework which is a great option for dashboard development. I personally really like this framework. It allows me to process my data along with its visualization through a web-based application.

Dash Framework

dash uses the plotly graphics library for plotting graphs. In addition to their graphic feature, these graphs also have a lot of good features (e.g. automatic scaling of axis for timestamp data, etc). Please refer dash documention for details.

Installation

Run following commands to install dash on your machine.

pip install dash==0.39.0  # The core dash backend
pip install dash-html-components==0.14.0  # HTML components
pip install dash-core-components==0.44.0  # dash core components
pip install dash-table==3.6.0  # Interactive DataTable component (new!)

First Dashboard Application

Now, we are going to develop our first dash application. For this application, we are going to plot the following data (some records are taken from here. This data has two attributes (House price and area).

Price Sq Ft
114300 1790
114200 2030
114800 1740
94700 1980
119800 2130
114600 1780

A dash application can have number of components (e.g. div block, table, headings, graph). In our application, we are going to use two components – heading and a graph. Let’s begin developing it. First of all, we need to import the required packages

import dash
import dash_core_components as dcc
import dash_html_components as html

The first package is used to create an object of dash application. Second package dash_core_components provides graph components and the third package allows us to include html components (heading, input box) in our application.

Next, we need to create a dash application.

app = dash.Dash(__name__)

__name__ is a special variable in python which contains name of current module. For instance, when you run your python program using command prompt then it contains __main__.

Now, we will create components to embed in your application. Just to have a clear idea, we want to create following structured with our application

<div>
 <h2> First Dash Application </h2>
 <graph> graph here.. </graph>
</div>

For <h2> component, we will use dash_html_components and for graph, we will use dash_core_components.

list_of_data = [{
    'y':[114300,114200,114800,94700,119800,114600],
    'x':[1790,2030,1740,1980,2130,1780],
    'type':'bar'
}]

body = html.Div([
    html.H2("First Dash Application"),
    dcc.Graph(id='first',
        figure={'data':list_of_data})
])

In the above code, we created the body of our application which is a div block. In this block, we created one H2 heading component and one Graph component. Graph has a attribute figure where we have specified the data to be plotted. This data (list_of_data) is actually a list of dictionaries (It might seems a bit confusing but you will be good after writing few codes). One important thing-> we used ‘type’:’bar’ which specify that we want to plot Bar chart.

Next, we will set the layout of the application.

app.layout = html.Div([body])

Finally, we will start the server

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

You can download this script from here

Now, we will execute our application. The execution of our application will start a server on the port 8050.


In order to see the output of the program, open your browser and type http://127.0.0.1:8050 in the address bar. It will show you the following screen

Complete list of dash_core_components.

Complete list of dash_html_components.

Adding CSS Stylesheets

The next step towards generating a beautiful dashboard is to add a styling feature. We can use css (what is css?) stylesheet in our application. It can be specified at the time of creating an application.

style = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.app = dash.Dash(__name__,external_stylesheets=style)
How to add local stylesheet?

With the above method, you can only add css which are available online. In case if you want to add your local css file, follow the given steps

  • Create a folder with name asset in the same directory where your dash script is stored.
  • Copy your stylesheet in the asset folder.
  • Add the path in your program
dash.Dash(__name__,external_stylesheets=["\asset\css-file-name"])

Note:Replace css-file-name with the name of your stylesheet name.

Installing Bootstrap component for dash

dash also supports Bootstrap (Introduction) which is a widely used css library. Its support can be added in your dash application using
dash-bootstrap-component package (complete documentation). It allows easy integration of Bootstrap in the dash application.
You can install it using the following command.

pip install dash-bootstrap-components

Now, let’s use it to add css to our first example.

dash Application with Bootstrap

We are going to create a following layout for our application. We will utilize Bootstrap’s grid system for structuring our components.

First, we need to import dash_bootstrap_components in our previous example.

import dash-bootstrap-components as dbc

Next, we will add bootstrap css to your program.

# dash-bootstrap-components has CDN for bootstrap css in dbc.themes.BOOTSTRAP
app = dash.Dash(__name__,external_stylesheets=[dbc.themes.BOOTSTRAP])

Now we will create our layout structure (first version)

body = dbc.Container(
    [   html.H1('With Bootstrap'),
        html.Hr(),
        dbc.Row(
            [
                dbc.Col(column_1,md=4),
                dbc.Col(column_2,md=8),
            ]
        )
    ]
)

Now as we have our layout structure, we will create content for column_1 and column_2.

column_1 = [
    html.H2("House Prices"),
    html.P("This is a demo application which shows house prices with house area."
    ),
    dbc.Button("Details", color="secondary"),
]
column_2 = [
    html.H2("Graph"),
    dcc.Graph(id='first',
        figure={'data':list_of_data}),
]

Note: You need to place the above code before the layout structure code.

Source code: here

Adding Event Handling

Let’s say you want to update visualizations in your app on the basis of the user’s input or particular events (e.g. selection of a radio button). This functionality can be easily added using dash which saves us a lot of time of coding manually the event handlers.

Let’s begin with a simple example. We are going to create a dash app with an input box. This application will display the text inserted in the input box.

First, we import following pacakge in the program

from dash.dependencies import Input, Output

Next, we need to create our layout with one Input box and one html Div block.

body = [ html.Div(id='output-box'), html.Input(id='input')]

app.layout = html.Div([body])
# Starting the server
if __name__ == "__main__":
    app.run_server(debug=True)

Now we need to specify that the value of Input box is connected with div block. It is done by writing a callback function. Callback function is responsible for updating the component.

@app.callback(Output('output-box','children'),[Input('input','value')]
def update(value):
    return 'You entered'+value

What’s the meaning of the above code? -> We specified that we are attaching a callback function with our application. This function gets called whenever the components with id input get a new value (whenever you enter anything in the Input box, its value gets updated). This callback function then update the value of the component with id output-box.

A callback function can have multiple Input but only one Output.


You can assign any name to your callback function. It will have as many parameters as many you have it’s Input. In our case, we have only one parameter.

Components have numerous attributes (e.g. an Input box has the id, value, style), you can specify in your callback which, attribute change will trigger the function execution. Similarly, you can specify which attribute you want to update in the Output component.

Source code: here

Output

File upload component

Adding a file component will allow users of your dashboard to upload their own file to generate visualizations of their data. dash also offer this functionality which we will learn in this section. Followings are the steps to add file upload functionality

  • Add file upload component
  • Add a callback with that component
  • Process the file content

First, we add the file upload component to our application.

body =  [
    dcc.Upload(
        id='upload-data',
        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='output-box')
]

We added style to our upload component. You can specify your own style as well.

Next, we will write callback function.

@app.callback(Output('output-box','children'),[Input('upload-data','contents')])
def update(value):
    return 'You entered '+str(value)

We are simply displaying the contents of the uploaded file. There is tricky part here. The contents are in binary which we need to encode ourselves (As you can see below)

Source code: version-1

We now encode the binary data of the file. The contents of file has file-type and file-data seperated by , (comma). So first, we need to extract the file-data using split() function. Next, we decode this data using base64.

def process_content(contents):
    type,data  = contents.split(',')
    decoded = base64.b64decode(data)
    return decoded
# Definfing callback with input and Output

@app.callback(Output('output-box','children'),[Input('upload-data','contents')])
def update(value):
    if value is not None:
        data = process_content(value)
        return str(data)

Output

Source code: version-2

In our current version of file upload application, there are still some issues e.g. new line characater \n shown in the output. We will handle this issue by converting our decoded content using utf-8 encoding.

def update(value):
    if value is not None:
        data = process_content(value)
        return str(data.decode('utf-8'))


Source code: version-3

If you are uploading a csv file, then the content of csv file will be in string. In order to use that string as file, you can use StringIO (below example).

In our final version of file upload, we will upload a csv file and print that. For processing the uploaded csv file, we are going to use Pandas library (Tutorial on Pandas library)

@app.callback(Output('output','children'),[Input('upload-data','contents')])
def update(value):
    if value is not None:
        data = process_content(value)
        df = pd.read_csv(io.StringIO(data.decode('utf-8')),names=['price','area'])
        data_table = dash_table.DataTable(
            data=df.to_dict('records'),
            columns=[{'name': i, 'id': i} for i in df.columns]
        )
        return data_table

Source code: here

Output

References

  1. P. Cortez and A. Silva. Using Data Mining to Predict Secondary School Student Performance. In A. Brito and J. Teixeira Eds., Proceedings of 5th FUture BUsiness TEChnology Conference (FUBUTEC 2008) pp. 5-12, Porto, Portugal, April, 2008, EUROSIS, ISBN 978-9077381-39-7.
 

admin