问题描述
我正在尝试创建一个具有CheckboxGroup小部件的Bokeh散点图,以根据相应的复选框状态显示或隐藏各个点.下面的代码段用于为每个点创建一个复选框,而Javascript则根据对复选框状态的更改来显示或隐藏散点图中的各个点.问题是我还需要标记散点图中的每个点.LabelSet可以很好地做到这一点.不幸的是,散点图上的标签将不会与其相应的散点图点同步显示或隐藏.LabelSet不接受视图参数,因此使用CDSView过滤散点图的方法对标签不起作用.所有标签始终保持可见.
I'm trying to create a Bokeh scatterplot with a CheckboxGroup widget to show or hide individual points based on the corresponding checkbox state. The code snippet below works to create a checkbox for each point, and the Javascript works to show or hide the respective points in the scatterplot based on changes to checkbox states. The problem is that I also need to label each point in the scatterplot. A LabelSet works fine to do this. Unfortunately, the labels on the scatterplot will not show or hide in sync with their respective scatterplot points. LabelSet does not accept a view argument, so the means of filtering the scatterplot with a CDSView does nothing for the labels. All the labels stay visible all the time.
source = ColumnDataSource(df)
active = list(range(len(df))
filter = IndexFilter(indices=active)
view = CDSView(source=source, filters=[filter])
p=figure(.....)
p.scatter(x='x', y='y', source=source, view=view)
labels = LabelSet(x='x', y='y', text='label', source=source)
p.add_layout(labels)
labelList = df['label'].astype(str).to_list()
labelSel = CheckboxGroup(labels=labelList, active=active)
callback = CustomJS(args=dict(src=source, filt=filter), code='''
filt.indices = cb_obj.active
src.change.emit()
''')
labelSel.js_on_change('active', callback)
layout = row(p, Spacer(width=20), labelSel)
show(layout)
我正在寻找一些帮助,以寻找一种与由CheckboxGroup驱动的IndexFilter过滤的散点图CDS同步过滤LabelSet CDS的方法.我希望有一些Javascript可以实现此目的,可能为LabelSet提供单独的CDS,但是我对Javascript不够好,无法提出解决方案.
I'm looking for some help in finding a way to filter the LabelSet CDS in sync with the scatterplot CDS as filtered by an IndexFilter driven by a CheckboxGroup. I expect that there is some Javascript that could make this happen, possibly with a separate CDS for the LabelSet, but I'm not good enough with Javascript to come up with a solution.
推荐答案
我找到了一种做我所需要的方法.看起来很丑陋且效率低下,但它确实有效.我为LabelSet创建了第二个CDS,然后使用JS使用CheckboxGroup状态从主CDS重建该CDS中的数据.如果您有更简洁,更优雅的方法,请随时做出回应.
I found a way to do what I need. It seems ugly and inefficient, but it works. I created a second CDS for the LabelSet and then used JS to rebuild the data in that CDS from the main CDS using the CheckboxGroup states. Please still feel free to respond if you have a much cleaner and more elegant way to do this.
source = ColumnDataSource(df)
lsource = ColumnDataSource(df)
active = list(range(len(df))
filter = IndexFilter(indices=active)
view = CDSView(source=source, filters=[filter])
p=figure(.....)
p.scatter(x='x', y='y', source=source, view=view)
labels = LabelSet(x='x', y='y', text='label', source=lsource)
p.add_layout(labels)
labelList = df['label'].astype(str).to_list()
labelSel = CheckboxGroup(labels=labelList, active=active)
callback = CustomJS(args=dict(src=source, lsrc=lsource, filt=filter), code='''
filt.indices = cb_obj.active;
src.change.emit();
var data=src.data;
var l=data['label'];
var x=data['x'];
var y=data['y'];
var ldata=lsrc.data;
var a=cb_obj.active;
var ll=[];
var lx=[];
var ly=[];
for(var i=0;i<a.length;i++){
ll.push(l[a[i]]);
lx.push(x[a[i]]);
ly.push(y[a[i]]);
}
ldata['label']=ll;
ldata['x']=lx;
ldata['y']=ly;
lsrc.change.emit();
''')
labelSel.js_on_change('active', callback)
layout = row(p, Spacer(width=20), labelSel)
show(layout)
这篇关于使用JavaScript过滤Bokeh LabelSet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!