Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
592 views
in Technique[技术] by (71.8m points)

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

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))
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...