简体   繁体   English

如何在Python的Bokeh的JavaScript回调中更新源?

[英]How to update a source in a JavaScript Callback of Bokeh in Python?

I am adapting this answer for my case, where I want an interactive, standalone graph where the slider selects which column of the data to plot in a bar chart. 我针对我的情况调整了这个答案 ,我想要一个交互式的独立图形,其中滑块选择要在条形图中绘制的数据列。 (Standalone is crucial, I cannot run a Bokeh server, thus the need for JavaScript callbacks .) (独立是至关重要的,我无法运行Bokeh服务器,因此需要JavaScript回调 。)

The data is a rectangle of floats with 100 rows in each of the 38 columns, which all have string labels like '40' etc. (This is how pandas .read_csv() handles numerics in the header by default.) Here is a sample from the top left corner (3x3, plus the row and column labels): 数据是一个浮动的矩形,在38列中每行都有100行,它们都具有字符串标签,例如'40'等(这是pandas .read_csv()默认情况下如何处理标头中的数字的方式。)从左上角开始(3x3,加上行和列标签):

        # ,        40,        41,        42,
   1.00000,   1.00000,   0.99287,   0.98489,
   2.00000,   1.00000,   0.99348,   0.98626,
   3.00000,   1.00000,   0.99433,   0.98922,

The code below produces the graph for the first column but does not update the graph upon moving the slider. 下面的代码生成第一列的图形,但是在移动滑块时不会更新图形。

By poking at it, I suspect the issue is with the JavaScript code, though ColumnDataSource remains a bit mysterious to me. 通过戳一下,我怀疑问题出在JavaScript代码,尽管ColumnDataSource对我而言仍然有点神秘。 (A more straightforward dictionary of numeric column labels to lists of the numbers in the column does not work as datasource_available , though corresponds to the linked answer's use case.) (数字列标签到列中数字列表的更直接的字典不适用于datasource_available ,尽管它对应于链接的答案的用例。)

datadf = pd.read_csv('male_survival_by_pctile.csv')
datadf.set_index('# ',inplace=True)
years = range(40,77)
data = {}
data_available = {}

for year in years:
    data[year] = {'top':datadf[str(year)],'x':range(1,101)}
data_available = ColumnDataSource.from_df(datadf)

from bokeh.core.properties import field
from bokeh.io import curdoc, output_notebook, show
from bokeh.layouts import layout, column
from bokeh.models import (ColumnDataSource, HoverTool, SingleIntervalTicker,
                          Slider, Button, Label, CustomJS)
from bokeh.plotting import figure

output_notebook()

source_visible = ColumnDataSource(data=dict(x=range(1,101),top=data_available[str(years[0])]))
source_available = ColumnDataSource(data=data_available)

plot = figure(output_backend="webgl")
plot.xaxis.ticker = SingleIntervalTicker(interval=.01)
plot.xaxis.axis_label = "Income percentile"
plot.yaxis.ticker = SingleIntervalTicker(interval=.05)
plot.yaxis.axis_label = "Survival rate"

label = Label(x=1.1, y=18, text=str(years[0]), text_font_size='70pt', text_color='#eeeeee')
plot.add_layout(label)

plot.vbar(top='top',x='x',width=1,source=source_visible)

slider = Slider(start=years[0], end=years[-1], value=years[0], step=1, title="Age")

slider.callback = CustomJS(
    args=dict(source_visible=source_visible,
              source_available=source_available), code="""
        var selected_function = cb_obj.get('value').toString();
        // Get the data from the data sources
        var data_visible = source_visible.get('data');
        var data_available = source_available.get('data');
        // Change bar height to the selected value
        data_visible.top = data_available[selected_function];
        // Update the plot
        source_visible.trigger('change');
    """)

layout = column(slider, plot)

show(layout)

The issue is in the CustomJS code as you suspected. 如您所怀疑,问题出在CustomJS代码中。 There are two things that need to be fixed. 有两件事需要修复。

  1. Bokeh has deprecated get() and set() methods and replaced them by getv() or setv() . Bokeh已弃用get()set()方法,并用getv()setv()代替了它们。 However, the preferred way of accessing or modifying model properties is through usual JavaScript attributes, eg, source_visible.data . 但是,访问或修改模型属性的首选方法是通过常规JavaScript属性(例如source_visible.data

  2. Bokeh has deprecated trigger('change') and replaced it by change.emit() . 散景已弃用了 trigger('change')并由change.emit()代替。

The fixed CustomJS code: 固定的CustomJS代码:

slider.callback = CustomJS(
    args=dict(source_visible=source_visible,
              source_available=source_available), code="""
        var selected_function = cb_obj.value.toString();
        // Get the data from the data sources
        var data_visible = source_visible.data;
        var data_available = source_available.data;
        // Change bar height to the selected value
        data_visible.top = data_available[selected_function];
        // Update the plot
        source_visible.change.emit();
    """)

JavaScript errors and warnings are seen in the browser's console. 在浏览器的控制台中可以看到JavaScript错误和警告。 Here are instructions for opening the console in different browsers . 以下是在不同浏览器中打开控制台的说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM