如何创建Bokeh Tap工具以选择ColumnDataSource中在给定列中共享相同值的所有点

jxr*_*mos 0 bokeh

我使用ColumnDataSource在散点图中绘制了一堆数据,一列是X坐标,另一列是Y坐标.第三列的患者ID可能有重复.我想创建一个Tap派生工具,它将选择在患者ID列中共享相同值的所有其他x,y坐标.

'x'  'y' 'ID'
 1    2   'p1'
 2    3   'p1'
 2    5   'p2'
 0    1   'p2'
Run Code Online (Sandbox Code Playgroud)

所以基本上如果我在我的散景散点图中点击坐标(1,2),我会得到(1,2)和(2,3)点的选择,而其他所有选择都未被选中,就像你如何找到套索和盒子选择工具一样.

Ant*_*ouc 5

以下是使用带有散景0.12.6的CustomJS的示例解决方案.基本上当用户选择一个字形时,你知道哪一行对应.查找关联的id值,然后将具有相同id的所有其他数据点添加到ColumnDataSource的selected属性中.

您也可以仅使用python创建等效的回调.但是,这将需要使用散景服务器.代码也非常相似.

# output to static HTML file
output_file("line.html")

p = figure(plot_width=400, plot_height=400,tools=["tap"])

x =[1,2,2,0]
y = [2,3,5,1]
n_id = ['p1','p1','p2','p2']
data = {'x':x,'y':y,'id':n_id}
source = ColumnDataSource(data)

# source callback
code = """
    var data = source.data,
        selected = source.selected['1d']['indices'],
        select_inds = [selected[0]];
    if(selected.length == 1){
        // only consider case where one glyph is selected by user
        selected_id = data['id'][selected[0]]
        for (var i = 0; i < data['x'].length; ++i){
            if(data['id'][i] == selected_id){
                // add all points to selected if their ids coincide with original
                // glyph that was clicked.
                select_inds.push(i)
            }
        }
    }
    source.selected['1d']['indices'] = select_inds 
    source.change.emit();
"""
callback = CustomJS(args={'source':source},code=code)
source.callback=callback
p.circle('x','y',source=source, size=20, color="navy", alpha=0.5)
# show the results
show(p)
Run Code Online (Sandbox Code Playgroud)

在最近的散景版本中,用于访问所选索引的符号已经有所简化.为了与bokeh 0.13.0兼容,JS回调可能变为:

code = """
    var data = source.data,
        selected = source.selected.indices,
        select_inds = [];
    if(selected.length == 1){
        // only consider case where one glyph is selected by user
        selected_id = data['id'][selected[0]]
        for (var i = 0; i < data['x'].length; ++i){
            if(data['id'][i] == selected_id){
                // add all points to selected if their ids coincide with original
                // glyph that was clicked.
                select_inds.push(i)
            }
        }
    }
    source.selected.indices = select_inds 
    source.change.emit();
"""
Run Code Online (Sandbox Code Playgroud)