Reputation: 827
I have my dataframe that looks like this:
travel_spending
state ethinicity
CA Asian 233.404580
MA Asian 748.117647
NY Asian 350.880000
CA Black 146.898148
MA Black 99.849057
NY Black 125.206897
CA Chinese 387.398601
MA Chinese 119.636364
NY Chinese 263.245283
CA Hispanic 131.156484
MA Hispanic 200.220859
NY Hispanic 175.738589
CA American Indian 36.500000
MA American Indian 67.500000
NY American Indian 81.800000
CA Japanese 365.029703
MA Japanese 28.666667
NY Japanese 241.500000
CA Other 257.953356
MA Other 208.178174
NY Other 255.144436
CA Portuguese 26.000000
MA Portuguese 22.000000
CA White 222.322485
MA White 167.293194
NY White 140.080838
From this dataframe, I generate subplots as follows:
import matplotlib.pyplot as plt
plt.style.use('ggplot')
plt.ion()
plt.rcParams['xtick.color']='k'
plt.rcParams['xtick.labelsize']='x-large'
travel_df_new.unstack(level=0).plot(kind='bar', subplots=True, legend=False)
Now I am trying to pass them to a HTML page using flask:
import sqlite3
import pandas as pd
from flask import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from io import BytesIO,StringIO
@app.route("/fig/")
def new_fig():
connection=sqlite3.connect('test.db')
query = "some sql query"
travel_df = pd.read_sql(query,connection)
plt.style.use('ggplot')
plt.ion()
plt.rcParams['xtick.color']='k'
plt.rcParams['xtick.labelsize']='x-large'
travel_df_new.unstack(level=0).plot(kind='bar', subplots=True, legend=False)
fig=plt.figure()
canvas = FigureCanvas(fig)
img = StringIO()
fig.savefig(img)
img.seek(0)
return send_file(img, mimetype='image/png')
@app.route('/image/')
def images():
return render_template("image.html")
Below is the image.html
<html>
<head>
<title>{{ title }} - image</title>
</head>
<body>
<img src="/fig/" alt="Image Placeholder">
</body>
</html>
Using the matplotlib.figure.Figure
i.e fig=plt.figure()
object and StringIO
i.e. img = StringIO()
and fig.savefig(img)
seems to be a standard way of accomplishing this. But I don't see any image on the HTML page.
Also, will using the plt.figure()
object help to display all the subgraphs?
Upvotes: 0
Views: 1065
Reputation: 2945
I think there are two main issues here, see my comments in the code:
travel_df_new.unstack(level=0).plot(kind='bar', subplots=True, legend=False)
# This creates a new, empty Figure. Saving this should just be an empty plot.
fig=plt.figure()
# Now you want to save the empty Figure into your img
# This won't work, because savefig works with BytesIO
canvas = FigureCanvas(fig)
img = StringIO()
fig.savefig(img)
img.seek(0)
Try something like this instead:
travel_df_new.unstack(level=0).plot(kind='bar', subplots=True, legend=False)
buff = BytesIO()
plt.savefig(buff, format='png', dpi=180)
buff.seek(0)
Note this uses io.BytesIO
instead of io. StringIO
, calls plt.savefig
and not fig.savefig
, and is a little more verbose in the savefig
arguments.
I'm also not quite sure why you call plt.ion()
in your route, you won't need interactive mode when run like this.
Upvotes: 3