首页 > 解决方案 > 无法更新选择 Bokeh Library 的 Select 小部件的值时的绘图

问题描述

我正在研究 COVID19 分析并使用 JSON 数据源。我已将 json 转换为数据框。我正在为每个状态在日期时间 x 轴上绘制每日病例、每日死亡和每日恢复的条形图,并且可以使用 Select 小部件选择状态。我不知道 Javascript,所以我试图避免使用 Javascript 回调,但一直在使用函数来更新 select.value。我不确定为什么即使我在 Bokeh 服务器上运行代码并且解释器没有引发异常,情节也没有得到更新。

有人可以为我提供任何可能导致问题的方向或帮助,因为我是 Python 新手并且感谢任何帮助?或者,如果有任何其他选择。此代码源自 [bokeh discourse][1] 上的类似情节

#Creating DataFrame
cases_summary = requests.get('https://api.rootnet.in/covid19-in/stats/history')
json_data = cases_summary.json()
cases_summary=pd.json_normalize(json_data['data'], record_path='regional', meta='day')
cases_summary['day']=pd.to_datetime(cases_summary['day'])
cases_summary['daily deaths']=cases_summary['deaths'].groupby(cases_summary['loc']).diff(1)
cases_summary['daily confirmed']=cases_summary['totalConfirmed'].groupby(cases_summary['loc']).diff(1)
cases_summary['daily discharged']=cases_summary['discharged'].groupby(cases_summary['loc']).diff(1)

#Initializing the first default plot
cases=cases_summary[cases_summary['loc']=='Delhi']


source=ColumnDataSource(data=cases)

a = figure(plot_width=1200, plot_height=700, sizing_mode="scale_both", x_axis_type='datetime')


def make_plot(cases_val):
    a.vbar('day', top='daily confirmed', width=timedelta(days=0.5),
                   legend_label='Daily Confirmed', color='#5e4fa2', source=cases_val)
    a.vbar('day', bottom='daily discharged', width=timedelta(days=0.5),
                        legend_label='Daily Recovered', color='#66c2a5', source=cases_val)
    a.vbar('day', bottom='daily deaths', width=timedelta(days=0.5),
                      legend_label='Daily Deaths', color='#3288bd', source=cases_val)
   return a

def update_plot(attr,old,new):
    location=select.value
    data_loc = cases_summary[cases_summary['loc'] == location]
    source = ColumnDataSource(data=dict()).from_df(data_loc)
    layout.children[0]=make_plot(source)

select = Select(title="Select State:", value="Delhi", options=cases_summary['loc'].unique().tolist())

plot = make_plot(cases)

controls = column(select)
layout = row(a, controls)
select.on_change('value', update_plot)

curdoc().add_root(layout)


  [1]: https://discourse.bokeh.org/t/how-to-update-the-bar-chart-that-has-dataframe-as-source-with-bokeh-select-widget/2031/8

标签: python-3.xbokehpandas-bokeh

解决方案


这可以使用视图和过滤器更简单地完成。这是另一种方法:

import requests
import pandas as pd
from bokeh.plotting import figure
from bokeh.layouts import column, row
from bokeh.io import curdoc
from bokeh.models import *
from datetime import timedelta

cases_summary = requests.get("https://api.rootnet.in/covid19-in/stats/history")
json_data = cases_summary.json()
cases_summary = pd.json_normalize(json_data["data"], record_path="regional", meta="day")
cases_summary["day"] = pd.to_datetime(cases_summary["day"])
cases_summary["daily deaths"] = (
    cases_summary["deaths"].groupby(cases_summary["loc"]).diff(1)
)
cases_summary["daily confirmed"] = (
    cases_summary["totalConfirmed"].groupby(cases_summary["loc"]).diff(1)
)
cases_summary["daily discharged"] = (
    cases_summary["discharged"].groupby(cases_summary["loc"]).diff(1)
)

source = ColumnDataSource(cases_summary)
filter = GroupFilter(column_name='loc',group='Delhi')
view = CDSView(source=source, filters = [filter])

a = figure(
    plot_width=1200, plot_height=700, sizing_mode="scale_both", x_axis_type="datetime"
)

a.vbar(
    "day",
    top="daily confirmed",
    width=timedelta(days=0.5),
    legend_label="Daily Confirmed",
    color="#5e4fa2",
    source=source,
    view = view
)

a.vbar(
    "day",
    bottom="daily discharged",
    width=timedelta(days=0.5),
    legend_label="Daily Recovered",
    color="#66c2a5",
    source=source,
    view = view
)

a.vbar(
    "day",
    bottom="daily deaths",
    width=timedelta(days=0.5),
    legend_label="Daily Deaths",
    color="#3288bd",
    source=source,
    view = view
)


def update_plot(attr, old, new):
    view.filters = [GroupFilter(column_name='loc',group=select.value)]

select = Select(
    title="Select State:", value="Delhi", options=cases_summary["loc"].unique().tolist()
)

controls = column(select)
layout = row(a, controls)
select.on_change("value", update_plot)

curdoc().add_root(layout)

推荐阅读