gpt4 book ai didi

python - Bokeh 多选小部件回调不起作用

转载 作者:太空宇宙 更新时间:2023-11-03 13:28:49 25 4
gpt4 key购买 nike

我是 Bokeh 的新手。最近尝试实现一些小部件回调并且很难在网上找到任何资源。

场景:我有一个包含公司列表的多选 Bokeh 小部件。根据选择的公司,必须更改 Vbar 中的数据。为此,我试图根据多选中的值更改 Vbar 中使用的数据源。我无法获得想要的结果。有人可以帮我解决这个问题吗?

我不擅长 CustomJs,因此在 Bokeh Server 上为 callabcks 做这件事。如果 CustomJs 也有解决方案,那将对我有很大帮助。

非常感谢您提前抽出时间!

下面是我使用的代码

source =source1[source1['year']== dt.now().year]
sourcex = source[source['month'] ==1 &
source['CompanyNo'].isin(['01','02','03','04','05','08']) ]

Overall= ColumnDataSource(source)
Curr= ColumnDataSource(sourcex)

boolinit = source['month']==1
view = CDSView(source=Overall, filters=[BooleanFilter(boolinit)])

hover3 = HoverTool(
tooltips = [
('day', '@day'),
('ExtendedPrice','@{ExtendedPrice}{0,0}'),
],
formatters = {
'day': 'datetime',
'ExtendedPrice': 'numeral'}
)

p = figure(
title='YEARLY SALES',
plot_width=600,
plot_height=400,
min_border=3,

tools = [hover3,'box_zoom','wheel_zoom', 'pan','reset'],
toolbar_location="above")
p.vbar(x='day', top='ExtendedPrice', width=0.2, color='#e8bc76',
source=Curr)
p.xaxis.axis_label = 'Day'
p.xaxis.axis_label_text_font_style = 'normal'
p.xaxis.axis_label_text_font_size = '12pt'
p.yaxis[0].formatter = NumeralTickFormatter(format="0,0")



def Multi_Selectupdate(attrname, old, new):

curr=sourcex[sourcex['CompanyNo'].isin(new)]
source.data=curr.data




companies=['All']+sourcex['CompanyNo'].unique().tolist()
multi_select = MultiSelect(title="Select:", value=['01'], options=companies,
height=200, width=100)

multi_select.on_change('value',Multi_Selectupdate )

layout = column(multi_select, p )

show(layout)

最佳答案

由于我没有数据,所以我使用以下脚本生成了它。我假设您的数据有 3 列 - Date , ExtendedPrice , CompanyNo .我首先生成了 10K 行的随机数据,然后在 CompanyNo 对其进行了汇总。 , day , month , year水平。

import pandas as pd
import random
CopmanyList = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15']

df = pd.DataFrame({'base' : ["2017-01-01" for t in range(10000)],
'Date' : [random.randint(0, 1035) for t in range(10000)],
'ExtendedPrice' : [random.random() for t in range(10000)],
'CompanyNo' : [CopmanyList[random.randint(0, 15)] for t in range(10000)]})

df['base'] = pd.to_datetime(df['base'])
df["Date2"] = df.apply(lambda x: x["base"] + timedelta(days=x['Date']), axis=1)
df.drop(['base', 'Date'], axis=1, inplace=True)
df.set_index('Date2', inplace=True)
df['month'] = df.index.month
df['year'] = df.index.year
df['day'] = df.index.day
source1=df.groupby(['year','month','day', 'CompanyNo'], as_index = False)['ExtendedPrice'].sum()
source =source1[source1['year']== dt.now().year]
sourcex = source[source['month'] ==1]
sourcex = sourcex[sourcex['CompanyNo'].isin(['01'])]
sourcex.sort_values(by='day', inplace=True)

现在,您想要完成的是给定一天和一组公司名称,您需要发布 ExtendedPrice 的某种聚合类型的条形图。 ,即假设公司“01”和“02”有 2 行(已选择),对于当年的第 2 个月(也由 slider 选择),这两个的 ExtendedPrice 值是 100,并且200. 如果我们想显示总和,您需要在条形图中显示 300。这个总结,你需要动态计算。

有两种方法可以实现。

<强>1。 Bokeh 回调

这将使用 native python 函数,但您需要使用 bokeh serve 运行它,例如 bokeh serve --show <filename.py> .看下面的代码,一个原生的python函数compsel正在过滤 pandas 数据框并对其进行汇总,并用新创建的数据替换图表后端数据 -

from datetime import timedelta
from datetime import datetime as dt
from bokeh.models.widgets import MultiSelect, Slider
from bokeh.layouts import widgetbox, column
from bokeh.models.ranges import FactorRange
from bokeh.plotting import figure, curdoc
from bokeh.models import ColumnDataSource, HoverTool, CustomJS

Overall= ColumnDataSource(source)
Curr= ColumnDataSource(sourcex[['day', 'ExtendedPrice']])
Curr.remove('index')

hover3 = HoverTool(tooltips = [('day', '@day'),('Sales','@{ExtendedPrice}{0,0.00}')],
formatters = {'day': 'datetime','Sales': 'numeral'})

p = figure(title='YEARLY SALES', plot_width=600, plot_height=400, min_border=3,
tools = [hover3,'box_zoom','wheel_zoom', 'pan','reset'],
toolbar_location="above")

r = p.vbar(x='day', top='ExtendedPrice', width=0.2, color='#e8bc76', source=Curr)
p.xaxis.axis_label = 'Day'
p.xaxis.axis_label_text_font_style = 'normal'
p.xaxis.axis_label_text_font_size = '12pt'

def compsel(attr, old, new):
vcomp = multi_select.value
vmonth = slider.value
sourcex = source[source['month'] ==vmonth]
sourcex = sourcex[sourcex['CompanyNo'].isin(vcomp)]
sourcex = sourcex.groupby(['day'], as_index = False)['ExtendedPrice'].sum()
Currnew= ColumnDataSource(sourcex[['day', 'ExtendedPrice']])
Currnew.remove('index')
r.data_source.data=Currnew.data


companies=source['CompanyNo'].unique().tolist()
companies.sort()
multi_select = MultiSelect(title="Select:", value=['01'], options=companies, height=200, width=100)
slider = Slider(start=1, end=12, value=1, step=1, title="Month")
slider.on_change("value", compsel)
multi_select.on_change("value", compsel)

layout = column(multi_select, slider, p)

curdoc().add_root(layout)

还有其他选项可以托管此应用程序。通过键入 bokeh serve --help 查看其他选项在终端

<强>2。 JavaScript 回调

这将生成一个 javascript 函数来与图表交互,它不需要 bokeh 服务器并直接在浏览器上工作。这将需要非常简单的 javascript 代码。在此处解决的示例中,我总结了 ExtendedPrice作为总和,但代码需要进行小的调整才能计算其他统计数据,例如意思是。这里的 js 回调函数做的事情与 bokeh 回调函数类似,它读取较大的数据集并根据选择和 slider 值对其进行过滤 -

source =source1[source1['year']== dt.now().year]
sourcex = source[source['month'] ==1]
sourcex = sourcex[sourcex['CompanyNo'].isin(['01'])]
sourcex.sort_values(by='day', inplace=True)

Overall= ColumnDataSource(source)
Curr= ColumnDataSource(sourcex[['day', 'ExtendedPrice']])
Curr.remove('index')

hover3 = HoverTool(tooltips = [('day', '@day'),('Sales','@{ExtendedPrice}{0,0.00}')],
formatters = {'day': 'datetime','Sales': 'numeral'})

p = figure(title='YEARLY SALES', plot_width=600, plot_height=400, min_border=3,
tools = [hover3,'box_zoom','wheel_zoom', 'pan','reset'],
toolbar_location="above")

r = p.vbar(x='day', top='ExtendedPrice', width=0.2, color='#e8bc76', source=Curr)
p.xaxis.axis_label = 'Day'
p.xaxis.axis_label_text_font_style = 'normal'
p.xaxis.axis_label_text_font_size = '12pt'

callms = CustomJS(args=dict(source=Overall, sc=Curr), code="""
var comp=msel.attributes.value;
var f = slider.value;
sc.data['ExtendedPrice'] = [];
sc.data['day'] = [];
for (var i = 0; i <= source.get_length(); i++){
if (source.data['month'][i] == f){
if (comp.indexOf(source.data['CompanyNo'][i]) >=0){
var d1 = source.data['day'][i]
if(typeof sc.data['day'][d1-1]=="undefined"){
sc.data['day'][d1-1] = d1
sc.data['ExtendedPrice'][d1-1] = source.data['ExtendedPrice'][i]
}
else{
sc.data['ExtendedPrice'][d1-1] = sc.data['ExtendedPrice'][d1-1] + source.data['ExtendedPrice'][i]
}
}
}
}
sc.change.emit();
""")

companies=source['CompanyNo'].unique().tolist()
companies.sort()
multi_select = MultiSelect(title="Select:", value=['01'], options=companies, height=200, width=100, callback=callms)
slider = Slider(start=1, end=12, value=1, step=1, title="Month", callback=callms)
callms.args["msel"] = multi_select
callms.args["slider"] = slider

layout = column(multi_select, slider, p)

output_file("Filterdata.html")
show(layout)

关于python - Bokeh 多选小部件回调不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50747006/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com