Visualising data on the web with Python and Dash

Dash is a user interface library for creating analytical web applications. Those who use Python for data analysis, data exploration, visualization, modelling, instrument control, and reporting will find immediate use for Dash.


Contents

1. Prerequsites

This documentation assumes some prior knowledge of Python. A minimum of being able to install Python, packages, and be able to execute code should get you a example visualisation. If you need assistance with Python, python.org provides documentation and tutorials.

The code in the snippets below is able to be copied verbatim into a file to create a visualisation. At the end of the document there is a link to download a file we prepared earlier.

In the interests of demonstrating the functionality, we have not presented best practice, rather focusing on demonstrating Dash. For example you might want to consider using a virtual environment to aid managing your third party packages.

2. Installation

The following tools should be available:

  • Browser capable of HTML 5.
  • Python (2.7 or 3.3 and above)

In order to run Dash in a Flask server the following libraries will need to be available:

  • dash (The core Dash back-end)
  • dash-renderer (Dash front-end)
  • dash-html-components(HTML components)
  • dash-core-components (Supercharged components)
  • plotly (Plotly graphing library)
  • pandas (Numerical Analysis and Data Manipulation)

Those have been pre-populated in a requirements.txt file, compatible with pip, to prepare a python environment.

3. About this example

In this example we are going to build a graph that shows life expectancy in comparison to GDP per capita based in all countries around the World.

4. First step

Besides Dash, we are using Pandas for extract and manipulate data and Plotly to render the output into a Graph. In order to use those libraries you first need to import them:

import dash
import dash_core_components as dcc
import dash_html_components as html

import plotly.graph_objs as go

import pandas as pd

5. Download and read a CSV file

Use Panda's read_csv function to download and extract your dataset. When you read a CSV, you get a DataFrame, which is made up of rows and columns. You access columns in a DataFrame the same way you access elements of a dictionary.

df = pd.read_csv('https://ndownloader.figsh.com/files/8261349')

6. Preview Dataset

Function head() gives you a preview of the downloaded dataset.

df.head()
Unnamed: 0 country continent population life expectancy gdp per capita
0 11 Afghanistan Asia 31889923.0 43.828 974.580338
1 23 Albania Europe 3600523.0 76.423 5937.029526
2 35 Algeria Africa 33333216.0 72.301 6223.367465
3 47 Angola Africa 12420476.0 42.731 4797.231267
4 59 Argentina Americas 40301927.0 75.320 12779.379640

7. Layout

Dash apps are composed of two parts: Layout and Interactivity. The first part is the "layout" of the app and it describes what the application looks like.

In this example we are going to create two kinds of filter:

  1. Countries: Multiple selection combo box with a list of all countries included on the Dataset
  2. Life Expectancy: Slider with a range of ages (min and max)
countries = df['country'].unique()

app = dash.Dash()

app.layout = html.Div([

    html.Div([
        html.Label('Country'),
        dcc.Dropdown(
            id='country',
            options=[{'label': i, 'value': i} for i in countries],
            value='',
            placeholder='Select...',
            multi=True
        )
    ],    
    style={'width': '20%', 'display': 'inline-block', 'margin-bottom': '20px'}),    

    html.Div([
        html.Label('Life Expectancy'),
        dcc.Slider(
            id='expectancy-slider',
            min=30,
            max=80,
            value=30,
            step=None,
            marks={'30':'>30', '40':'>40', '50':'>50', '60':'>60', '70':'>70', '80':'>80'}
        ),
    ],
    style={'width': '20%', 'display': 'inline-block', 'margin-bottom': '20px', 'margin-left': '20px'}),

    html.Div([
        dcc.Graph(id='life-exp-vs-gdp'),
    ],
    style={'width': '70%'}),
])

8. Interactivity

Dash provides a simple reactive decorator for binding your custom data analysis code to your Dash user interface.
When an input element changes (e.g. when you select an item in the dropdown or drag the slider), Dash’s decorator provides your Python code with the new value of the input.
In this example we are calling the update_graph function each time either a country is selected or a life expectancy range is set.

@app.callback(
    dash.dependencies.Output('life-exp-vs-gdp', 'figure'),
    [
        dash.dependencies.Input('expectancy-slider', 'value'),
        dash.dependencies.Input('country', 'value')
    ])
def update_graph(expectancy, country):

    filtered_df = df.loc[df["life expectancy"] > expectancy]

    if (country != '' and country is not None):
        filtered_df = filtered_df[df.country.str.contains('|'.join(country))]

    traces = []
    for i in filtered_df.continent.unique():
        df_by_continent = filtered_df[filtered_df['continent'] == i]
        traces.append(go.Scatter(
            x=df_by_continent['gdp per capita'],
            y=df_by_continent['life expectancy'],
            text=df_by_continent['country'],
            mode='markers',
            opacity=0.7,
            marker={
                'size': 15,
                'line': {'width': 0.5, 'color': 'white'}
            },
            name=i
        ))

    return {
        'data': traces,
        'layout': go.Layout(
            xaxis={'title': 'GDP Per Capita', 'titlefont': dict(size=18, color='darkgrey'), 'zeroline': False, 'ticks': 'outside' },
            yaxis={'title': 'Life Expectancy', 'titlefont': dict(size=18, color='darkgrey'), 'range': [30, 90], 'ticks': 'outside'},
            margin={'l': 60, 'b': 60, 't': 30, 'r': 20},
            legend={'x': 1, 'y': 1},
            hovermode='closest'
        )
    }

9. Style

Every aesthetic element of the app is customisable: The sizing, the positioning, the colors, the fonts. Dash apps are built and published in the Web, so the full power of CSS is available.

Use app.css.append_css in order to set an external CSS file

app.css.append_css({
    "external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})

10. Running

Dash apps are web applications. Dash uses Flask as the web framework. The underlying Flask app is available at app.server, and for the purpose of running the application you should call run_server function in your python code as you can see below.

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

We have prepared the code snippets from above in dash_example.py. It is strongly recommended you read this file to understand it before executing it.

If it all works correctly, your app should be running and accessible in your web browser; the default address is http://127.0.0.1:8050/. It should look something like this:


Related technologies: