Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show a pandas dataframe as a flask-boostrap table?

I would like to show a pandas dataframe as a boostrap-html table with flask, thus I tried the following:

The data (.csv table):

Name    Birth Month Origin  Age Gender
Carly   Jan Uk  10  F
Rachel  Sep UK  20  F
Nicky   Sep MEX 30  F
Wendy   Oct UK  40  F
Judith  Nov MEX 39  F

The python code (python_script.py):

from flask import *
import pandas as pd
app = Flask(__name__)

@app.route("/tables")
def show_tables():
    data = pd.read_csv('table.csv')
    data.set_index(['Name'], inplace=True)
    data.index.name=None
    females = data.loc[data.Gender=='f']
    return render_template('view.html',tables=[females.to_html(classes='female')],

    titles = ['na', 'Female surfers'])


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

The templates directory (view.html):

<!doctype html>
<title>Simple tables</title>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class=page>
  <h1>Surfer groups</h1>
  {% for table in tables %}
    <h2>{{titles[loop.index]}}</h2>
    {{ table|safe }}
  {% endfor %}
</div>

The boostrap style.css:

body            { font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;}
a, h1, h2       { color: #377ba8; }
h1, h2          { margin: 0; }
h1              { border-bottom: 2px solid #eee; }
h2              { font-size: 1.2em; }

table.dataframe, .dataframe th, .dataframe td {
  border: none;
  border-bottom: 1px solid #C8C8C8;
  border-collapse: collapse;
  text-align:left;
  padding: 10px;
  margin-bottom: 40px;
  font-size: 0.9em;
}

.male th {
    background-color: #add8e6;
    color: white;
}

.female th {
    background-color: #77dd77;
    color: white;
}

tr:nth-child(odd)       { background-color:#eee; }
tr:nth-child(even)  { background-color:#fff; }

tr:hover            { background-color: #ffff99;}

So far, when I run my python_script.py:

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger pin code: 123-221-151

I got two issues: a Not Found error and when I go to http://127.0.0.1:5000/tables I got an builtins.KeyError KeyError: 'Name'. Any idea of how to show a pandas dataframe as a table with pandas and flask?.

like image 200
tumbleweed Avatar asked Mar 11 '23 04:03

tumbleweed


1 Answers

The problem here is with the data.csv file. When you do read_csv() on it:

In [45]: pd.read_csv("/tmp/a.csv")
Out[45]: 
  Name    Birth Month Origin  Age Gender
0                  Carly   Jan Uk  10  F
1                  Rachel  Sep UK  20  F
2                  Nicky   Sep MEX 30  F
3                  Wendy   Oct UK  40  F
4                  Judith  Nov MEX 39  F

In [46]: df = pd.read_csv("/tmp/a.csv")

In [47]: df.columns
Out[47]: Index([u'Name    Birth Month Origin  Age Gender'], dtype='object')

As you can see, there is only one column, instead of four, because it can't understand that 'Birth Month' is supposed to be one column. To fix this, you can open the file and change the first line to:

"Name" "Birth Month" "Origin"  "Age" "Gender"

And, then while reading the csv:

In [62]: pd.read_csv("/tmp/a.csv", sep='\s+', quotechar='"')
Out[62]: 
     Name Birth Month Origin  Age Gender
0   Carly         Jan     Uk   10      F
1  Rachel         Sep     UK   20      F
2   Nicky         Sep    MEX   30      F
3   Wendy         Oct     UK   40      F
4  Judith         Nov    MEX   39      F

Or you could have also just changed Birth Month to Birth_Month

For the '404 Not Found' error, the problem is that you have not defined any route for '/'. So, (after editing the header of the csv) I would do something like:

from flask import *
import pandas as pd
app = Flask(__name__)

@app.route("/tables")
def show_tables():
    data = pd.read_csv("/tmp/a.csv", sep='\s+', quotechar='"')
    data.set_index(['Name'], inplace=True)
    data.index.name=None
    females = data.loc[data.Gender=='F']
    return render_template('view.html',tables=[females.to_html(classes='female')],

    titles = ['na', 'Female surfers'])

@app.route("/")
def show_home():
    return "Hello Guys! Visit: <a href='/tables'> this link </a>"

if __name__ == "__main__":
    app.run(debug=True)
like image 112
Nehal J Wani Avatar answered Mar 20 '23 09:03

Nehal J Wani