我正在尝试创建一个使用customJS回调链接到选择小部件的Bokeh数据表。我的想法是,当我更改选择时,数据表将更新为仅显示与所选选择值对应的相关行。我的守则如下:
from bokeh.io import output_file, show
from bokeh.layouts import widgetbox
from bokeh.models.widgets import Select, DataTable, TableColumn
from bokeh.models.sources import ColumnDataSource, CDSView
from bokeh.models import CustomJS
output_file("CatDog.html")
select = Select(title="Animal", options=["Cat","Dog"])
source=ColumnDataSource(data=dict(Animal=["Cat","Cat","Cat","Cat","Dog","Dog","Dog","Dog",],Breed=["Siamese","Persian","Bengal","Burmese","Lab","Golden", "Poodle","Pug"]))
filteredSource = ColumnDataSource(data=dict(Animal=[],Breed=[]))
columns = [TableColumn(field="Animal",title="Animal"),TableColumn(field="Breed",title="Breed",sortable=True)]
callback = CustomJS(args=dict(source=source,filteredSource = filteredSource), code="""
var data = source.data;
var f = cb_obj.value;
var d2 = filteredSource.data;
d2['Animal']=[]
d2['Breed']=[]
for(i = 0; i < data['Animal'].length;i++){
if(data['Animal'][i]==f){
d2['Animal'].push(data['Animal'][i])
d2['Breed'].push(data['Breed'][i])
}
}
alert(d2['Breed'])
filteredSource.change.emit()
""")
select.js_on_change('value',callback)
data_table=DataTable(source=filteredSource,columns=columns )
data_table_unfiltered=DataTable(source=source,columns=columns )
show(widgetbox(data_table,select,data_table_unfiltered))
警报会正确显示我期望的行,具体取决于选择的类别,但&#34; filteredSource&#34; DataTable不会更新,它会保持空白。任何指导将不胜感激!
答案 0 :(得分:1)
这似乎使这项工作,您需要触发数据表本身的更改。实际上在此之前已经问过这个问题:Bokeh DataTable won't update after trigger('change') without clicking on header
尽管如此,将代码稍微重新排列到下面可以解决问题(使用散景0.12.14)
from bokeh.io import output_file, show
from bokeh.layouts import widgetbox
from bokeh.models.widgets import Select, DataTable, TableColumn
from bokeh.models.sources import ColumnDataSource, CDSView
from bokeh.models import CustomJS
output_file("CatDog.html")
select = Select(title="Animal", options=["Cat","Dog"])
source=ColumnDataSource(data=dict(Animal=["Cat","Cat","Cat","Cat","Dog","Dog","Dog","Dog",],Breed=["Siamese","Persian","Bengal","Burmese","Lab","Golden", "Poodle","Pug"]))
filteredSource = ColumnDataSource(data=dict(Animal=[],Breed=[]))
columns = [TableColumn(field="Animal",title="Animal"),
TableColumn(field="Breed",title="Breed",sortable=True)]
data_table=DataTable(source=filteredSource,columns=columns, width=800 )
data_table_unfiltered=DataTable(source=source,columns=columns, width=800 )
callback = CustomJS(args=dict(source=source,
filteredSource=filteredSource,
data_table=data_table), code="""
var data = source.data;
var f = cb_obj.value;
var d2 = filteredSource.data;
d2['Animal']=[]
d2['Breed']=[]
for(i = 0; i < data['Animal'].length;i++){
if(data['Animal'][i]==f){
d2['Animal'].push(data['Animal'][i])
d2['Breed'].push(data['Breed'][i])
}
}
filteredSource.change.emit()
// trigger change on datatable
data_table.change.emit()
""")
select.js_on_change('value',callback)
show(widgetbox(data_table,select,data_table_unfiltered))
答案 1 :(得分:0)
以下是使用CDSView和BooleanFilter的更新答案。 使用Bokeh 2.2.3运行
from bokeh.models import CDSView, BooleanFilter
from bokeh.io import show, output_notebook
from bokeh.layouts import column
from bokeh.models.widgets import Select, DataTable, TableColumn
from bokeh.models.sources import ColumnDataSource, CDSView
from bokeh.models import CustomJS
output_notebook()
select = Select(title="Animal", options=["All","Cat","Dog"])
source=ColumnDataSource(data=dict(Animal=["Cat","Cat","Cat","Cat","Dog","Dog","Dog","Dog"],
Breed=["Siamese","Persian","Bengal","Burmese","Lab","Golden", "Poodle","Pug"]))
booleans = [True for i in source.data['Animal']]
view1 = CDSView(source=source, filters=[BooleanFilter(booleans)])
columns = [TableColumn(field="Animal", title="Animal"),
TableColumn(field="Breed", title="Breed", sortable=True)]
data_table = DataTable(source=source, columns=columns, width=800, view=view1)
callback = CustomJS(args=dict(source=source, view=view1), code="""
var data = source.data;
var f = cb_obj.value;
for(var i = 0; i < data['Animal'].length; i++){
if(data['Animal'][i] == f || f == 'All'){
view.filters[0].booleans[i] = true;
} else {
view.filters[0].booleans[i] = false;
}
}
source.change.emit();
""")
select.js_on_change('value',callback)
show(column(select, data_table))```