Сервер Bokeh - Как манипулировать выделением в функции обратного вызова - PullRequest
0 голосов
/ 23 мая 2018

Я строю несколько патчей, сгруппированных по категории «группа» в источнике данных.Чего бы я хотел добиться, так это: щелкнув по одному патчу, нужно выделить не только сам патч, но и все патчи одной и той же группы.

Я обнаружил, что ColumnDataSource имеет атрибут выбран .Однако манипулирование этим атрибутом в функции обратного вызова не дает желаемого эффекта.

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 Ответ

0 голосов
/ 24 мая 2018

Вы можете сделать выбор в Javascript, но если вы действительно хотите сделать это в Python, вот пример:

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)
...