Как связать мультиселектный виджет с данными, используя bokeh в блокноте jupyter? - PullRequest
0 голосов
/ 13 июня 2018

Я пытаюсь соединить таблицу данных с виджетом с множественным выбором в bokeh.Я искал и обнаружил, что мне нужно разработать функцию для обновления источника данных для таблицы данных, но у меня, похоже, есть две проблемы.

  1. Кажется, я не могу получить доступ к значению объекта множественного выбора после того, как щелкнул по нему.
  2. Кажется, я не могу передать изменения в записную книжку после получения изменения.

Вот пример моего кода:

import pandas as pd
from bokeh.io import push_notebook
from bokeh.plotting import show, output_notebook
from bokeh.layouts import row
from bokeh.models.widgets import MultiSelect, DataTable, TableColumn
from bokeh.models import ColumnDataSource

output_notebook()

df=pd.DataFrame({'year':[2000,2001,2000,2001,2000,2001,2000,2001],
              'color':['red','blue','green','red','blue','green','red','blue'],
              'value':[ 0,1,2,3,4,5,6,7]})

columns=[TableColumn(field=x, title=x) for x in df.columns]
source=ColumnDataSource(df)
data_table=DataTable(source=source,columns=columns)

years=[2000,2001,2000,2001,2000,2001,2000,2001]

## MultiSelect won't let me store an integer value, so I convert them to strings

multi=MultiSelect(title="Select a Year", value=['2000','2001'],options=[str(y) for y in set(years)])

def update(attr,old, new):
    yr=multi.value
    yr_vals=[int(y) for y in yr]
    new_data=df[df.year.isin(yr_vals)]
    source.data=new_data
    push_notebook(handle=t)

multi.on_change('value',update)
t=show(row(multi,data_table),notebook_handle=True)

1 Ответ

0 голосов
/ 14 июня 2018

push_notebook является однонаправленным.Таким образом, вы можете передавать изменения только из ядра IPython, в интерфейс JavaScript.Никакие изменения из пользовательского интерфейса не передаются обратно в работающее ядро ​​Python.Другими словами, on_change бесполезен (без дополнительной работы, см. Ниже). Если вы хотите такого рода взаимодействие, есть несколько вариантов:

  • Использование ipywidgets с push_notebook.Обычно это включало функцию interact для автоматической генерации простого пользовательского интерфейса с обратными вызовами, которые используют push_notebook для обновления графиков и т. Д. На основе значений виджета.Просто для ясности, этот подход использует ipywidgets, которые не встроенные виджеты Bokeh.Вы можете увидеть полный пример записной книжки здесь:

    https://github.com/bokeh/bokeh/blob/master/examples/howto/notebook_comms/Jupyter%20Interactors.ipynb

  • Встроить серверное приложение Bokeh.Сервер Bokeh - это то, что позволяет on_change обратным вызовам на виджетах Bokeh функционировать.Как правило, это включает создание функции, которая определяет приложение (указав, как создается новый документ):

    def modify_doc(doc):
        df = sea_surface_temperature.copy()
        source = ColumnDataSource(data=df)
    
        plot = figure(x_axis_type='datetime', y_range=(0, 25))
        plot.line('time', 'temperature', source=source)
    
        def callback(attr, old, new):
            if new == 0:
                data = df
            else:
                data = df.rolling('{0}D'.format(new)).mean()
            source.data = ColumnDataSource(data=data).data
    
        slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
        slider.on_change('value', callback)
    
        doc.add_root(column(slider, plot))
    

    Затем вызывается show для этой функции:

    show(modify_doc)
    

    Полныйпример записной книжки здесь:

    https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/notebook_embed.ipynb

  • (опция Hacky) некоторые люди объединили обратные вызовы CustomJS с JS-функцией Jupyers kernel.execute для распространения значений обратно в ядро.

...