首页 > 解决方案 > Bokeh plot Hovertool 在测试中工作,但相同的代码在 Flask 应用程序中不起作用

问题描述

我一直在尝试将 Bokeh 绘图合并到我的 Flask Web 应用程序中,并且遇到了我的绘图在呈现为 html 文件时可以正常工作的问题,但是显示 ??? 在我的 Flask 应用程序中运行时在 Hovertool 中。绘图的其余部分正常运行。

起初,我认为我的 html 文件如何渲染绘图是一个问题,但后来我注意到,如果我重组我的代码并直接在 Sublime 中运行它而不是启动我的应用程序并从页面运行,我会遇到同样的问题。奇怪的是,如果我将所有内容保存在一个 .py 文件中而不导入,则该图将作为独立的 .html 文件正常工作。我不希望这样做以使我的代码更易于管理,因为我将生成大量绘图。下面是我的文件代码。如果您在我导入的方式中看到会导致 state_trend_month_mean() 方法/函数出现问题的情况,请告诉我。

此外,一旦我开始工作,我将把我的绘图格式转移到它自己的函数中。抱歉,看起来很糟糕的代码。还在学习。另一件事,由于类似的问题,我正在将我的 df 转换为字典,这是我能够正确渲染我的图的唯一方法。我敢肯定是因为我缺乏经验。

这是我将生成图表的代码。final_df.two_year_df() 是从另一个 .py 返回和导入的数据帧。工具提示@nti_per_day 是 df/dict 中的一列,但散景显示为 ??? 在悬停工具中

在此处输入图像描述

import pandas as pd
from bokeh.plotting import figure, output_file, show
from bokeh.models import ColumnDataSource, FactorRange, Label, Title, NumeralTickFormatter, BasicTickFormatter
from bokeh.models.tools import HoverTool
from bokeh.models.tickers import MonthsTicker
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn
from bokeh.layouts import widgetbox, column
from datetime import date, datetime
from dateutil.relativedelta import relativedelta
from vgt_web_app.final_df import FinalDF as final_df
from math import pi


class Graphs():

    def state_trend_month_mean():
        df = final_df.two_year_df()
        dict_1 = df.groupby(['month_year'], as_index=False).sum().to_dict('list')
        y_max = max(dict_1['nti_per_day_yoy']) * 1.1
        y_min = y_max * -.25

        source = ColumnDataSource(data=dict(dict_1))

        tooltips = [("Daily NTI", "@nti_per_day")]

        tools_to_show = 'pan,box_zoom, wheel_zoom,save,reset'
        p = figure(plot_width=600, plot_height=300, x_axis_type="datetime", name="bar1", sizing_mode='scale_both',
                             toolbar_location='below', toolbar_sticky=False, tools=tools_to_show, y_range=(y_min, y_max))
        p.vbar(x='month_year', top='nti_per_day_yoy', width=1800000000, source=source, color='#5886a5')

        p.title.text = 'Year over Year (YoY) - State Avg NTI Trend'
        p.xaxis.axis_label = 'Month/Year'
        p.yaxis.axis_label = 'Avg NTI YoY'
        p.xaxis.major_label_orientation = pi/4
        p.xaxis.ticker = MonthsTicker(months=list(range(1,13)))
        p.xaxis.fixed_location = 0
        p.yaxis.formatter = NumeralTickFormatter(format='$0,0')
        p.background_fill_alpha = 0.80
        p.xgrid.grid_line_color = None
        p.ygrid.grid_line_color = None
        p.add_tools(HoverTool(tooltips=tooltips, mode='mouse'))
        return(p)

这是routes.py

from flask import render_template, request, Blueprint
from bokeh.embed import components
from vgt_web_app.graphs import Graphs as graphs

reports = Blueprint('reports', __name__)

@reports.route('/reports')
def il_reports():
    g = graphs.state_trend_month_mean()
    # graph_data = g
    graph_data = g
    script, div = components(graph_data)
    return render_template('reports.html', title='Reports', graph_data=graph_data, script=script, div=div)

这是html。仍然是基本的,一旦我能正确展示这个情节就会改进

{% extends "layout.html" %}
{% block content %}
<!DOCTYPE html>
<html lang="en">

<script src="https://cdnjs.cloudflare.com/ajax/libs/bokeh/2.1.1/bokeh.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bokeh/2.1.1/bokeh-widgets.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bokeh/2.1.1/bokeh-tables.min.js"></script>

<body>
    <h1>Reports</h1>

    {{ div | safe }}
    {{ script | safe }}


</body>

{% endblock content %}

图表再次具有所有功能,但它具有 ??? 在悬停中

标签: pythonhtmlflaskbokeh

解决方案


只看到???一次表明一件事:您在工具提示中指定的列名在ColumnDataSource. 考虑到您在问题中指定了一个列名:

@nti_per_day_yoy 是 df/dict 中的一列

但在实际代码中,您指定的内容略有不同:

tooltips = [("Daily NTI", "@nti_per_day")]

最可能的解释是您在工具提示中给出了错误的列名。


推荐阅读