Bokeh server - How to manipulate a selection in a callback function

前提是你 提交于 2019-12-04 01:42:48

问题


I am plotting several patches that are grouped by a category "group" in the data source. What would I like to achieve is the following: By clicking on one patch, not only the patch itself but all patches of the same group should be highlighted as selected.

I found that ColumnDataSource has an attribute selected. However, manipulating this attribute in the callback function does not have the desired effect.

import os
from bokeh.models import ColumnDataSource, Patches
from bokeh.plotting import figure
from bokeh.layouts import row
from bokeh.io import output_file, curdoc
import pandas as pd

x = [[1,2,4], [3,5,6], [7,9,7], [5,7,6]]
y = [[4,2,1], [6,5,8], [3,9,6], [2,2,1]]
group = ['A', 'A', 'B', 'B']
id = [0,1,2,3]

df = pd.DataFrame(data=dict(x=x, y=y, group=group, id=id))
source = ColumnDataSource(df)

p = figure(tools="tap")

renderer = p.patches('x', 'y', source=source)

# Event handler
def my_tap_handler(attr,old,new):
    global source
    group_name = source.data['group'][new['1d']['indices'][0]]
    group_indices = df['id'][df['group'] == group_name]
    source.selected.indices = list(group_indices)
    print("source.selected.indices", source.selected.indices)


selected_patches = Patches(fill_color="#a6cee3")
renderer.selection_glyph = selected_patches

# Event
renderer.data_source.on_change("selected", my_tap_handler)

#######################################
# Set up layouts and add to document
curdoc().add_root(row(p, width=800))

回答1:


You can do the selection in Javascript, but if you really want to do this in Python, here is an example:

import os
from bokeh.models import ColumnDataSource, Patches, CustomJS
from bokeh.plotting import figure
from bokeh.layouts import row
from bokeh.io import output_file, curdoc
import pandas as pd

def app(doc):
    x = [[1,2,4], [3,5,6], [7,9,7], [5,7,6]]
    y = [[4,2,1], [6,5,8], [3,9,6], [2,2,1]]
    group = ['A', 'A', 'B', 'B']
    id = [0,1,2,3]

    df = pd.DataFrame(data=dict(x=x, y=y, group=group, id=id))
    source = ColumnDataSource(df)

    p = figure(tools="tap")

    renderer = p.patches('x', 'y', source=source)

    def my_tap_handler(attr,old,new):
        indices = source.selected.indices
        if len(indices) == 1:
            group = source.data["group"][indices[0]]
            new_indices = [i for i, g in enumerate(source.data["group"]) if g == group]
            if new_indices != indices:
                source.selected = Selection(indices=new_indices)

    selected_patches = Patches(fill_color="#a6cee3")
    renderer.selection_glyph = selected_patches
    source.on_change("selected", my_tap_handler)

    doc.add_root(row(p, width=800))

show(app)


来源:https://stackoverflow.com/questions/50492995/bokeh-server-how-to-manipulate-a-selection-in-a-callback-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!