【问题标题】:Interactive bokeh visualization - graph not updating交互式散景可视化 - 图形未更新
【发布时间】:2020-08-01 16:42:10
【问题描述】:

我是 python 和散景的相对新手,并试图创建一个按国家/地区划分的 COVID 发病率和死亡人数的交互式散景图。 该代码在没有选择工具的情况下可以完美运行,但是当我使用选择工具重写它时,我执行它时,图形不会随着新的选择而更新。 我显然在一些基本问题上出错了,但我根本无法弄清楚这一点。 这段代码应该为任何正在检查的人独立运行。我不确定我是否搞砸了更新功能,或者更新变量是否不起作用。

import pandas as pd
from bokeh.plotting import figure, output_file
from bokeh.io import curdoc
from bokeh.models import ColumnDataSource, HoverTool, NumeralTickFormatter, DatetimeTickFormatter, Select
from bokeh.palettes import Category20b
from bokeh.layouts import layout

url_confirmed = 'https://data.humdata.org/hxlproxy/api/data-preview.csv?url=https%3A%2F%2Fraw.githubusercontent.com%2FCSSEGISandData%2FCOVID-19%2Fmaster%2Fcsse_covid_19_data%2Fcsse_covid_19_time_series%2Ftime_series_covid19_confirmed_global.csv&filename=time_series_covid19_confirmed_global.csv'
url_deaths = 'https://data.humdata.org/hxlproxy/api/data-preview.csv?url=https%3A%2F%2Fraw.githubusercontent.com%2FCSSEGISandData%2FCOVID-19%2Fmaster%2Fcsse_covid_19_data%2Fcsse_covid_19_time_series%2Ftime_series_covid19_deaths_global.csv&filename=time_series_covid19_deaths_global.csv'


covid_confirmed = pd.read_csv(url_confirmed)
covid_confirmed_grp = covid_confirmed.groupby('Country/Region').sum()
covid_deaths = pd.read_csv(url_deaths)
covid_deaths_grp = covid_deaths.groupby('Country/Region').sum()


covid_confirmed_dates = covid_confirmed_grp.drop(columns = ['Lat', 'Long'])
covid_confirmed_dates = covid_confirmed_dates.transpose()
covid_confirmed_dates = covid_confirmed_dates.reset_index()
covid_confirmed_dates = covid_confirmed_dates.rename(columns = {'index':'date'})
covid_confirmed_dates['date'] = pd.to_datetime(covid_confirmed_dates['date'])


covid_deaths_dates = covid_deaths_grp.drop(columns = ['Lat', 'Long'])
covid_deaths_dates = covid_deaths_dates.transpose()
covid_deaths_dates = covid_deaths_dates.reset_index()
covid_deaths_dates = covid_deaths_dates.rename(columns = {'index':'date'})
covid_deaths_dates['date'] = pd.to_datetime(covid_deaths_dates['date'])


countrylist = covid_confirmed_dates.columns.tolist()
countrylist.remove('date')

# reset the output so that the file size does not increase
#bokeh.io.reset_output()

source_confirmed = ColumnDataSource(covid_confirmed_dates)
source_deaths = ColumnDataSource(covid_deaths_dates)
countrylist = ['India','US', 'Spain', "Italy", "Germany", "United Kingdom", 
               "France", "China", "Iran", "Turkey", "Belgium", 
               "Brazil", "Canada", "Netherlands", "Switzerland"]
mypallette = Category20b[20]
country = 'India'

# name the output file
output_file('covid_confirmed_deaths.html')

def update_country(attr,old,new):
    global country
    country = select.value

# define the figure variable
f = figure(plot_width=800, plot_height=500, x_axis_type="datetime")

f.xaxis.axis_label = "Date"
f.yaxis.axis_label = "Cases"
f.title.text = 'COVID19 Cases'

f.line(x = 'date', y = country, color='red', alpha=1, source = source_confirmed, line_width = 3, name = country, legend_label=country)

f.legend.location = "top_left"
f.legend.click_policy="hide"
f.legend.title = 'Tap to toggle on/off'
f.yaxis[0].formatter = NumeralTickFormatter(format="0,000,000")
f.xaxis[0].formatter = DatetimeTickFormatter(days="%d/%m")
hover = HoverTool(
    tooltips = [
        ("country", "$name"),
        ("date", "@date{%d/%m}"),
        ("cases", "$y{0,000,000}")
    ],
    formatters={
        '@date': 'datetime',
        },
    )
f.add_tools(hover)

# define the figure variable
g = figure(plot_width=800, plot_height=500, x_axis_type="datetime")

g.xaxis.axis_label = "Date"
g.yaxis.axis_label = "Deaths"
g.title.text = 'COVID19 Deaths'

g.line(x = 'date', y = country, color='blue', alpha=1, source = source_deaths, line_width = 3, name = country, legend_label=country)

g.legend.location = "top_left"
g.legend.click_policy="hide"
g.legend.title = 'Tap to toggle on/off'
g.yaxis[0].formatter = NumeralTickFormatter(format="0,000,000")
g.xaxis[0].formatter = DatetimeTickFormatter(days="%d/%m")
hover = HoverTool(
    tooltips = [
        ("country", "$name"),
        ("date", "@date{%d/%m}"),
        ("cases", "$y{0,000,000}")
    ],
    formatters={
        '@date': 'datetime',
        },
    )
g.add_tools(hover)

countrylist1 = [('India', 'India'),('US','US'), ('Spain', 'Spain'), 
               ('Italy', 'Italy'), ('Germany', 'Germany'), ('United Kingdom', 'United Kingdom'), 
               ('France', 'France'), ('China', 'China'), ('Iran', 'Iran'),('Turkey', 'Turkey'), ('Belgium', 'Belgium'),
               ('Brazil', 'Brazil'), ('Canada', 'Canada'), ('Netherlands', 'Netherlands'), ('Switzerland', 'Switzerland')]
select = Select(title="Select Country:", value="India", options=countrylist1)
select.on_change("value", update_country)

lay_out=layout([[select]])
curdoc().add_root(lay_out)
curdoc().add_root(f)
curdoc().add_root(g)

【问题讨论】:

    标签: python bokeh interactive


    【解决方案1】:

    为了让 Bokeh 了解您所做的更改,您必须将这些更改应用到 Bokeh 模型。大多数时候它是一个数据源,但它可以是任何其他模型。例如。当你调用f.line() 时,它会返回一个GlyphRenderer 的实例。要更改其y 属性,您可以使用renderer.glyph.y = select.valuename 也一样。

    不过,legend_label 更难做到。问题是,它不是一个属性,而只是一种创建Legend 模型实例并自动为您设置其所有机制的便捷方式。为了更改图例标签,您必须深入研究图例的工作方式并更改正确模型的正确属性。

    【讨论】:

    • 谢谢。那么我应该在更新功能中使用:f.line.glyph.y = select.value - 或者我应该如何使用它?我不确定 f.line 是否有属性字形。
    • 不,不是f.line.something。而是renderer = f.line(...); renderer.glyph.y = ...
    • 非常感谢。它与renderer = f.line(...) 一起使用,然后在更新功能中使用renderer.glyph.y = select.valuerenderer.name = select.value。我必须摆脱传说,这很好,因为我一次只策划一个国家。我将尝试更新 ColumnDataSource 的新版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-06
    • 2012-02-09
    • 2019-06-23
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    相关资源
    最近更新 更多