【问题标题】:Passing matplotlib subplots generated from a pandas dataframe to HTML for display using flask将从 pandas 数据框生成的 matplotlib 子图传递到 HTML 以使用烧瓶显示
【发布时间】:2017-09-30 23:52:56
【问题描述】:

我的数据框如下所示:

    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

从这个数据框中,我生成子图如下:

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)

现在我正在尝试使用烧瓶将它们传递给 HTML 页面:

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")

下面是image.html

   <html>
  <head>
    <title>{{ title }} - image</title>
  </head>
  <body>
    <img src="/fig/" alt="Image Placeholder">
  </body>
</html>

使用matplotlib.figure.Figurefig=plt.figure() 对象和StringIOimg = StringIO()fig.savefig(img) 似乎是实现此目的的标准方法。但是我在 HTML 页面上看不到任何图像。

另外,使用plt.figure() 对象是否有助于显示所有子图?

【问题讨论】:

    标签: python html pandas matplotlib flask


    【解决方案1】:

    我觉得这里主要有两个问题,在代码中看我的cmets:

    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)
    

    试试这样的方法:

    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)
    

    注意这里使用io.BytesIO而不是io. StringIO,调用plt.savefig而不是fig.savefig,并且在savefig参数中更加冗长。

    我也不太清楚你为什么在路由中调用plt.ion(),这样运行时不需要交互模式。

    【讨论】:

    • 只要提到plt.savefig 只是调用fig.savefig 如果fig 是当前数字。没有区别,两者的论点相同。
    • 正确,@optimus_prime 可以通过plt.gcf() 获取当前数据,但创建新数据不是正确的方法。
    猜你喜欢
    • 2013-12-05
    • 2017-10-20
    • 2019-01-11
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 2022-11-13
    • 1970-01-01
    相关资源
    最近更新 更多