Bokeh MultiSelect widget回调不工作

2024-10-01 04:47:34 发布

您现在位置:Python中文网/ 问答频道 /正文

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

场景:我有一个带有公司列表的multi-_-select-bokeh小部件。根据选择的公司,Vbar中的数据必须更改。为此,我尝试根据Multi-select中的值更改Vbar中使用的数据源。我无法得到想要的结果。有人能帮我解决这个问题吗。在

我不擅长CustomJs,因此在Bokeh服务器上进行调用。如果在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) 

Tags: source部件公司widthselectmultilabelday
1条回答
网友
1楼 · 发布于 2024-10-01 04:47:34

因为我没有数据,所以我使用以下脚本生成它。我假设您的数据有3列-DateExtendedPriceCompanyNo。我首先生成了10K行的随机数据,然后在CompanyNodaymonthyear级别对其进行了总结。在

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个月(也由滑块选择),这两个月的ExtendedPrice值为100,和200。如果我们想显示总数,你需要在条形图中显示300。这个总结,你需要动态计算。在

有两种方法可以做到这一点。在

1。Bokeh回调

{cdg>你需要使用这个函数。请看下面的代码,一个原生python函数compsel正在过滤pandas dataframe并对其进行汇总,然后用新创建的数据替换图表后端数据-

^{pr2}$

还有其他选项可以托管此应用程序。在终端中输入bokeh serve help,查看其他选项

2。JavaScript回调

这将生成一个javascript函数来与图表交互,它不需要bokeh服务器,直接在浏览器上工作。这将需要非常简单的javascript代码。在这里解决的示例中,我将ExtendedPrice总结为sum,但是代码将需要一些小的调整来计算其他统计信息,例如平均值。这里的js回调函数与bokeh回调函数的作用类似,它读取更大的数据集并根据select和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)

相关问题 更多 >