Share @ LinkedIn Facebook  dashboard, plotly, dash, pythonanywhere
How to build dashboard using Python (Dash & Plotly) and deploy online (pythonanywhere.com)

How to build a dashboard using Python (Dash & Plotly) and deploy online (Pythonanywhere.com)

Organizations around the world nowadays are collecting data. Analyzing collected data and presenting it visually is very common nowadays. One can use python libraries like matplotlib, seaborn in jupyter notebook and share it with their colleagues. But it has few limitations like plots are static and a person viewing results needs to start a jupyter server in order to run notebook.

Now, what if a person who is from management and needs interactive graphs and need to share it further with people without technical background who can't run a jupyter notebook?

One can design interactive visualization dashboards using javascript libraries like d3.js, chartjs, threejs, reactjs, leaflet etc.

But what if a person is a python developer and does not want to involve in web development technologies like javascript, CSS, etc.

We have designed this tutorial for such people who want to create a dashboard using their knowledge of Python and want to share it with others.

This tutorial will be explaining how to use python libraries plotly(for creating interactive visualization) and dash (Assembling visualization to create dashboard) to create interactive dashboard working on local and then deploy it for free on pythonanywhere.com so that it can be shared with anyone by just giving a link. A person can visit the link and analyze the dashboard.

1. Creating Dashboard On Local

We'll first make dashboard working on local and then deploy it to pythonanywhere.com.We'll start by installing the latest version of plotly and dash libraries on local.

In [ ]:
!pip install --upgrade dash plotly sklearn

Loading IRIS Dataset

As a part of this tutorial, we'll be using a simple IRIS flower dataset available in scikit-learn for analysis purposes. IRIS dataset has size information about 150 samples of 3 different flower types (iris-setosa, iris-virginica, iris-versicolor). Let's load the IRIS dataset.

In [1]:
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
iris = load_iris() ## It returns simple dictionary like object with all data.
print("IRIS Dataset Size : ",iris.data.shape, iris.target.shape)
print("IRIS Flower Names : ", iris.target_names)
print("IRIS Flower Feature Names : ", iris.feature_names)

## Creating dataframe of total data
iris_df = pd.DataFrame(data=np.concatenate((iris.data,iris.target.reshape(-1,1)), axis=1), columns=(iris.feature_names+['Flower Type']))
iris_df["Flower Name"] = [iris.target_names[int(i)] for i in iris_df["Flower Type"]]
iris_df.head()
IRIS Dataset Size :  (150, 4) (150,)
IRIS Flower Names :  ['setosa' 'versicolor' 'virginica']
IRIS Flower Feature Names :  ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
Out[1]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) Flower Type Flower Name
0 5.1 3.5 1.4 0.2 0.0 setosa
1 4.9 3.0 1.4 0.2 0.0 setosa
2 4.7 3.2 1.3 0.2 0.0 setosa
3 4.6 3.1 1.5 0.2 0.0 setosa
4 5.0 3.6 1.4 0.2 0.0 setosa

We'll be including four simple graphs in our dashboard which will be interactive.

  • Scatter Plot depicting a relationship between sepal length and petal length features of flower color-encoded by flower name
  • Scatter Plot depicting a relationship between sepal width and petal width features of flower color-encoded by flower name
  • Histogram showing distributions of sepal length (cm) color-encoded by flower name
  • Box Plot showing a concentration of sepal width (cm) by flower types in a dataset.

Plotting Interactive Graphs Independently

We'll first plot all graphs independently and then incorporate them into a dashboard.

Scatter Plot depicting the relationship between sepal length and petal length features of flower color-encoded by flower name

In [2]:
import plotly.express as px
In [ ]:
chart1 = px.scatter(data_frame=iris_df,
           x="sepal length (cm)",
           y="petal length (cm)",
           color="Flower Name",
           size=[1.0]*150,
           title="sepal length (cm) vs petal length (cm) color-encoded by flower type")
chart1

Scatter Plot 1

Scatter Plot depicting the relationship between sepal width and petal width features of flower color-encoded by flower name

In [ ]:
chart2 = px.scatter(data_frame=iris_df,
           x="sepal width (cm)",
           y="petal width (cm)",
           color="Flower Name",
           size=[1.0]*150,
           title="sepal width (cm) vs petal width (cm) color-encoded by flower type")
chart2

Scatter Plot 2

Histogram showing distributions of sepal length (cm) color-encoded by flower name

In [ ]:
chart3 = px.histogram(data_frame=iris_df,
             x="sepal length (cm)",
             color="Flower Name",
             title="Distributions of sepal length (cm) color-encoded by flower name")
chart3

Histogram

Box Plot showing concentration of sepal width (cm) by flower types in dataset.

In [ ]:
chart4 = px.box(data_frame=iris_df,
           x="Flower Name",
           y="sepal width (cm)",
           color="Flower Name",
           title="concentration of sepal width (cm) by flower types")
chart4

Box Plot

Integrating Charts Into Dashboard

We'll now use the dash library to create a dashboard consisting of these 4 charts put as four boxes into a dashboard.

Import dash components & Initialize Dashboard App

We first need to import the necessary dash core and HTML modules. We then need to initialize the dashboard by creating an app of it.

NOTE: Please make a note that we are using external CSS which will be responsible for the look of the dashboard. Experience web developers can replace it with their style sheets and modify the look and feel of a dashboard as needed.

In [7]:
import dash
import dash_core_components as dcc
import dash_html_components as html

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

Embed Each Graphs Into Dash Components

We first need to wrap each graph into core dash components so that they can be easily integrated with other dash html components. We'll wrap each graph into Graph core components of the dashboard. Here, className="six columns" is little CSS part of stylesheet used above for look-feel of dashboard. It'll take up half screen space for keeping the graph.

In [8]:
graph1 = dcc.Graph(
        id='graph1',
        figure=chart1,
        className="six columns"
    )

graph2 = dcc.Graph(
        id='graph2',
        figure=chart2,
        className="six columns"
    )

graph3 = dcc.Graph(
        id='graph3',
        figure=chart3,
        className="six columns"
    )

graph4 = dcc.Graph(
        id='graph4',
        figure=chart4,
        className="six columns"
    )

Create HTML Layout of Dashboard

We'll now create 2 rows of html.Div components. Both rows will have 2 graphs as their children along with the dashboard header. Please make a note that we have also created html.H2 heading component which will be used to show heading of dashboard. We also have used simple CSS with the style attribute of last html.Div. One can modify the look and feel of a dashboard by providing style details with there parameters in each dash html components.

In [9]:
header = html.H2(children="IRIS Dataset Analysis")

row1 = html.Div(children=[graph1, graph3],)

row2 = html.Div(children=[graph2, graph4])

layout = html.Div(children=[header, row1, row2], style={"text-align": "center"})

Setting Layout of Dashboard

We now just need to set layout as the layout of the dashboard app initialized at the beginning.

In [10]:
app.layout = layout

Putting All Together and Bringing Dashboard Up on Local

We'll now put all the contents described above in a simple file called iris_analysis.py and run it. It'll bring up a dashboard on the localhost at port 8050.

iris_analysis.py

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris

import plotly.express as px


import dash
import dash_core_components as dcc
import dash_html_components as html

iris = load_iris() ## It returns simple dictionary like object with all data.

## Creating dataframe of total data
iris_df = pd.DataFrame(data=np.concatenate((iris.data,iris.target.reshape(-1,1)), axis=1), columns=(iris.feature_names+['Flower Type']))
iris_df["Flower Name"] = [iris.target_names[int(i)] for i in iris_df["Flower Type"]]

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)


header = html.H2(children="IRIS Dataset Analysis")

chart1 = px.scatter(data_frame=iris_df,
           x="sepal length (cm)",
           y="petal length (cm)",
           color="Flower Name",
           size=[1.0]*150,
           title="sepal length (cm) vs petal length (cm) color-encoded by flower type")


graph1 = dcc.Graph(
        id='graph1',
        figure=chart1,
        className="six columns"
    )

chart2 = px.scatter(data_frame=iris_df,
           x="sepal width (cm)",
           y="petal width (cm)",
           color="Flower Name",
           size=[1.0]*150,
           title="sepal width (cm) vs petal width (cm) color-encoded by flower type")


graph2 = dcc.Graph(
        id='graph2',
        figure=chart2,
        className="six columns"
    )

chart3 = px.histogram(data_frame=iris_df,
             x="sepal length (cm)",
             color="Flower Name",
             title="Distributions of sepal length (cm) color-encoded by flower name")

graph3 = dcc.Graph(
        id='graph3',
        figure=chart3,
        className="six columns"
    )

chart4 = px.box(data_frame=iris_df,
           x="Flower Name",
           y="sepal width (cm)",
           color="Flower Name",
           title="concentration of sepal width (cm) by flower types")


graph4 = dcc.Graph(
        id='graph4',
        figure=chart4,
        className="six columns"
    )



row1 = html.Div(children=[graph1, graph3],)

row2 = html.Div(children=[graph2, graph4])

layout = html.Div(children=[header, row1, row2], style={"text-align": "center"})

app.layout = layout

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

We'll now run it local.

Shell Showing Dashboard Server

Below how our server will look when tried to access from 127.0.0.1:8050 in a browser.

Dashboard

2. Deploying Dashboard on pythonanywhere.com

We'll now provide step by step guide on deploying above server to pythonanywhere.com. Please create a free beginner account with pythonanywhere.com to follow along.

  • Login to pythonanywhere.com
  • Go to Web tab from top and click on Add a new web app button to create new web app. WebApp Creation Tab

  • Select Flask as framework for keeping dashboard. Flask

  • Select Python 3.8 from next screen and click on next. It'll create flask project named mysite and keep flask server file(flask_app.py) in that folder file. Clicking next on that screen will create our flask app which will be used for deploying our dashboard and handling requests. Python38 Flask App File

  • Go to Dashboard of pythonanywhere.com by clicking on the link at the top.

  • Click on the bash button below New Console. It'll start a new bash shell for us.
  • Install dash, plotly, and sklearn using this bash shell. Please execute below command in shell.
    • pip3.8 install --upgrade --user plotly dash sklearn
    • Please make a note that you need to use pip version according to your python version else you'll face an error saying no dash module found.
  • Go to Dashboard of pythonanywhere.com click on Browse files
  • Go to mysite folder and upload iris_analysis.py file there. Please delete flask_app.py file.
  • Click on Web link at the top again to go to settings of a web app. Scroll below and an open file named WSGI Configuration file.
  • Make below-mentioned changes to file whose name ends with _wsgi.py.

    • Comment line which imports flask_app
    • Import app from iris_analysis as plotly_app
    • Set value of application variable as plotly_app.server and save changes. WSGI File Changes
  • Go to Web app setting tab by clicking on Web from the dashboard of pythonanywhere.com. Click on the reload button to bring up a server with the above-mentioned changes to the WSGI Configuration file. Reloading Server With Changes

  • Access Dashboard from URL https://coderzcolumn.pythonanywhere.com/

NOTE You can force https usage from the web settings page.

DASHBOARD URL: https://coderzcolumn.pythonanywhere.com/

Please feel free to check our URL for the live dashboard and let us know your views.


Sunny Solanki  Sunny Solanki