Фильтрация набора меток Bokeh с Javascript - PullRequest
0 голосов
/ 12 июля 2020

Я пытаюсь создать диаграмму рассеяния Bokeh с виджетом CheckboxGroup, чтобы показать или скрыть отдельные точки в зависимости от соответствующего состояния флажка. Приведенный ниже фрагмент кода предназначен для создания флажка для каждой точки, а Javascript работает для отображения или скрытия соответствующих точек на диаграмме рассеивания на основе изменений состояний флажков. Проблема в том, что мне также нужно пометить каждую точку на диаграмме рассеяния. Для этого отлично работает LabelSet. К сожалению, метки на диаграмме рассеивания не будут отображаться или скрываться синхронно c с соответствующими точками диаграммы рассеяния. LabelSet не принимает аргумент представления, поэтому средства фильтрации диаграммы рассеяния с помощью CDSView ничего не делают для меток. Все метки остаются видимыми все время. CheckboxGroup. Я ожидаю, что есть некие Javascript, которые могли бы это сделать, возможно, с отдельным CDS для LabelSet, но я недостаточно хорош с Javascript, чтобы найти решение.

1 Ответ

0 голосов
/ 12 июля 2020

Я нашел способ делать то, что мне нужно. Это кажется некрасивым и неэффективным, но это работает. Я создал второй CDS для LabelSet, а затем использовал JS для восстановления данных в этом CDS из основного CDS с использованием состояний CheckboxGroup. Не стесняйтесь отвечать, если у вас есть более чистый и элегантный способ сделать это.

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