Flask + Plotly Dashboard

Last week I had 3 days to come up with a visualization dashboard. My backend choice was flask (we are inseparable) however I had to choose the easiest plotting package. The choices that I had was between plotly, dash and bokeh. Looking at the bokeh documentation, I found that it was straight forward. However, one of the cons that I had found was: working with categorical data. While all the other packages work seamlessly with categorical data, one has to do some hacks when it comes to bokeh. This made me to look for an alternative. The others were plotly or its dashboard Dash. Now it may seem obvious that one would choose Dash, however I like being in control of the front-end (I am not afraid of going head to head with css, js and html). That is why I decided to go with plotly.

Installing Dependancies

pip install flask
pip install plotly
pip install pandas #will need it to manipulate the data
pip install numpy

Creating the flask application

The structure of the application will be as shown below.  The static folder will be used to store all the css, js and image files. If you are using any bootstrap template, this is where you will store the files. All the html files will be in the template folder

Application Structure

The python file will have the following initial code.

from flask import Flask

app = Flask(__name__)


@app.route('/')
def index():
    return 'Hello World!'


if __name__ == '__main__':
    app.run()

When you run the file you will have a see Hello World in the url  http://localhost:5000/

We will then create a html named index.html and save in the template folder. The file will first have a basic code:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>My First Dashboard</title>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6">
            <div class="chart" id="bargraph">

            </div>
        </div>
    </div>
</div>
</body>
</html>

We will then change the python file to render the html file. Notice that we had to add render template in the imports.

from flask import Flask, render_template #this has changed

app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html') #this has changed


if __name__ == '__main__':
    app.run()

First Plot

We will the plot a bar graph as shown in the plotly. We will create a function that will return the plot. Now this where I fell in love with this package. The simplicity of rendering the plot. However to discover this was not easy. This is why  I decided to share this.

First let us import all the dependencies:

import plotly
import plotly.graph_objs as go

import pandas as pd
import numpy as np
import json

The create plot function will have following code. We will create our own sample dataframe, if you have a file you will replace it with the dataframe:

def create_plot():


    N = 40
    x = np.linspace(0, 1, N)
    y = np.random.randn(N)
    df = pd.DataFrame({'x': x, 'y': y}) # creating a sample dataframe


    data = [
        go.Bar(
            x=df['x'], # assign x as the dataframe column 'x'
            y=df['y']
        )
    ]

    graphJSON = json.dumps(data, cls=plotly.utils.PlotlyJSONEncoder)

    return graphJSON

The json variable is what will be rendered on the index function with the html file. This how we will do it:

@app.route('/')
def index():

    bar = create_plot()
    return render_template('index.html', plot=bar)

Now on the html file, we will use the variable to plot. We will have to add the plotly and d3 javascript for  the plot to show. The code for plotting a graph using a jinja2 variable is shown below:

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<div class="chart" id="bargraph">
    <script>
        var graphs = {{plot | safe}};
        Plotly.plot('bargraph',graphs,{});
    </script>
</div>

Note that the div class has to chart for the plot to show. When you run the python file and reload the page, you should see a bar graph:

First Plot

Congratulation! You have added a plot on a html. This is the basics. we can go ahead and style it. I will not cover that in this blog. What I would like to finish with is adding ajax calls.

Creating plot with ajax calls

It took sometime for me to be able to figure this out. Plotly.js to the rescue. Lets add a dropdown that we will use to change the type of plot.

<div class="col-xs-3">
    <label> Choose the plot type....</label>
    <select class="form-control" id ='first_cat'>
        <option value="Bar">Bar</option>
        <option value="Scatter">Scatter</option>
    </select>
</div>

Now lets create a javascript called plots.js that will have the ajax function on change. We will return the json variable of the plot.

$('#first_cat').on('change',function(){

    $.ajax({
        url: "/bar",
        type: "GET",
        contentType: 'application/json;charset=UTF-8',
        data: {
            'selected': document.getElementById('first_cat').value

        },
        dataType:"json",
        success: function (data) {
            Plotly.newPlot('bargraph', data );
        }
    });
})

The ajax function will take the selected variable from the dropdown and pass it to a function in flask, with a route /bar then it will return the plot. The code on the flask end is as follows:

@app.route('/bar', methods=['GET', 'POST'])
def change_features():

    feature = request.args['selected']
    graphJSON= create_plot(feature)

    return graphJSON

I had to edit the create plot function so as to accommodate the selection of the plots. The new code is as follows:

def create_plot(feature):
    if feature == 'Bar':
        N = 40
        x = np.linspace(0, 1, N)
        y = np.random.randn(N)
        df = pd.DataFrame({'x': x, 'y': y}) # creating a sample dataframe
        data = [
            go.Bar(
                x=df['x'], # assign x as the dataframe column 'x'
                y=df['y']
            )
        ]
    else:
        N = 1000
        random_x = np.random.randn(N)
        random_y = np.random.randn(N)

        # Create a trace
        data = [go.Scatter(
            x = random_x,
            y = random_y,
            mode = 'markers'
        )]


    graphJSON = json.dumps(data, cls=plotly.utils.PlotlyJSONEncoder)

    return graphJSON

Do not forget to add jquery javascript to your index.html and the plot.js

<script src="{{ url_for('static', filename='js/jquery-1.11.1.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/plots.js') }}"></script>

With those changes, we can run our python file again. When we select the scatter plot option, you should be able to see the plot.:

Scatter Plot

With that you can get going with creating dashboards.

Full code can be found on this link

35 Replies to “Flask + Plotly Dashboard”

  1. Plotly.newPlot(‘bargraph’, data )

    You might want to change the id name to something generic since it is no more only ‘bargraph’

    Also,
    Many thanks for the tutorial.

  2. Thanks a lot for this tutorial.
    Straight-forward, useful and fairly complete.

    1. You can style the page using normal css code. As for the graphs, check some of parameters of the graphs. You can alter color, line style, markers. Its similar to matplotlib.

    1. Hello,
      Yes it is. Place them on two different . The code syntax will be the same as is on index.html . What changes will be the name variables.

  3. When i am running it , it show me like that only >

    graph-0
    graph-1
    graph-2

    Whats the wrong ?
    Thanks

  4. Just fantastic that sometimes you’re wondering whether something is possible, and then stumble upon such a perfect tutorial. Thanks!!

  5. Please your help.

    could you please give me example of how can we style it. I have tried but with success.

    Thanks in advance.

  6. This is great, exactly what i was looking for. I’m working with dash but with this i can use plotly in personal hobby websites as well. Thanks for sharing!

  7. Great tutorial! I’d recently started using Flask for a personal website (after having used dash for a bit), and i felt using the html templates was way easier than using the html function/class in dash (not sure which it is).
    Have you tried to or had any success getting callbacks from the charts (example, data from a point you clicked on)?

  8. This is great article! I recently started using Flask for a personal website, and I found I much prefer jinga templates to the plotly html library and was thinking about this exact thing.
    One question, have you been able to get dash style callback data from the chart? Example, x/y/name data on click?

  9. I am getting empty plot. i m plotting a normal pie plot using plotly and passing the plot in variable to html

  10. Nice one, thank you.

    I think you aren’t using HTTP POST requests here though, you don’t need the `methods=[‘GET’, ‘POST’]`, “selected” is just a request parameter here, passed as `/bar?selected=’Bar’`.

  11. Tanks so much!!
    It was so useful and important to me.
    You made a wonderful work.
    Congratulations!!

  12. awesome ! exactly what I was looking for … for long time!
    thank you to share with us this tutorial , and present how plotly can be “unblocked” from flask ! very valuable …
    appreciated your work.

  13. Thanks so much for this! It was very straightforward and exactly what I need to get started using plotly and Flask.

  14. Ms. Wambui –
    Thank you for taking the time to put this post together.
    I’m writing this 30 months after you posted it and as you can tell from all the comments, it’s still very helpful – especially for us Python/Flask newbies.
    Tom

Comments are closed.