Como adicionar um retorno de chamada ao DataTable Bokeh?

12

Estou tentando usar o Bokeh para criar uma DataTable editável que atualize os dados de origem quando os dados forem editados. Eu comecei com o exemplo padrão DataTable aqui , e fiz o kwarg editável para verdade. Aqui é onde eu estou:

from datetime import date
from random import randint

from bokeh.models import ColumnDataSource, Callback
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn
from bokeh.io import output_file, output_notebook, show, vform
output_notebook()
data = dict(dates=[date(2014, 3, i+1) for i in range(10)],
            downloads=[randint(0, 100) for i in range(10)])

source = ColumnDataSource(data)

columns = [TableColumn(field="dates", title="Date", formatter=DateFormatter()),
           TableColumn(field="downloads", title="Downloads")]

callback = Callback(args=dict(Source=source), code="""
       console.log( '#cell edited')""")

data_table = DataTable(source=source, columns=columns, width=400, height=280, editable=True)
data_table.on_change(callback,source)
show(vform(data_table))

Isso cria uma tabela de dados editável, mas não consigo descobrir como obter o retorno de chamada para atualizar os dados de origem ou para configurar os dados de origem para que eles façam isso automaticamente. Eu pensei que havia uma maneira de fazer isso automaticamente com ColumnDataSource e depois de tentar que tentou escrever um retorno de chamada. No entanto, parece que o DataTable não tem uma opção de retorno de chamada, mas estranhamente tem um atributo on_change.

Alguém sabe como fazer isso?

    
por Kyle Siegel 01.09.2015 в 02:30
fonte

2 respostas

2

O código a seguir detectará o evento de clicar (selecionar) uma linha ou linhas. Eu coloquei alguns console.log para produzir as linhas selecionadas.

from datetime import date
from random import randint
import bokeh
import bokeh.plotting 

data = dict(dates=[date(2014, 3, i+1) for i in range(10)],
            downloads=[randint(0, 100) for i in range(10)])

source = bokeh.models.ColumnDataSource(data)

columns = [bokeh.models.TableColumn(field="dates", title="Date",
           formatter=bokeh.models.DateFormatter()),
           bokeh.models.TableColumn(field="downloads", title="Downloads")]

source.callback = bokeh.models.CustomJS(args=dict(source=source), code="""
       console.log( '#Selected rows:');
       var indices = source.selected["1d"].indices;
       for (var i = 0; i<indices.length; i++){
           console.log(i+":"+indices[i]);
       }
       """)

data_table = bokeh.models.DataTable(source=source, columns=columns, 
                                    width=400, height=280, editable=True)

bokeh.io.output_notebook()
bokeh.io.show(data_table)
    
por Pablo Reyes 01.12.2016 / 23:34
fonte
2

Isso funciona na versão 0.12.14 do Bokeh. Os dados de origem são atualizados com editable=True e o retorno de chamada on_change é chamado quando o atributo data é atualizado:

from bokeh.models import ColumnDataSource
from bokeh.models.widgets import DataTable, TableColumn, HTMLTemplateFormatter
from bokeh.io import curdoc

dict1 = {
    'x':[0]*6,
    'y':[0,1,0,1,0,1]
}
source = ColumnDataSource(data=dict1)

columns = [
    TableColumn(field="x", title="x"),
    TableColumn(field="y", title="y")
]

data_table = DataTable(
    source=source,
    columns=columns,
    width=800,
    editable=True,
)

def on_change_data_source(attr, old, new):
    print('-- OLD DATA: {}'.format(old))
    print('-- NEW DATA: {}'.format(new))
    print('-- SOURCE DATA: {}'.format(source.data))

    # to check changes in the 'y' column:
    indices = list(range(len(old['y'])))
    changes = [(i,j,k) for i,j,k in zip(indices, old['y'], new['y']) if j != k]
    if changes != []:
        for t in changes:  # t = (index, old_val, new_val)
            patch = {
                'y' : [(t[0], int(t[2])), ]   # the new value is received as a string
            }
            source.patch(patch)   # this will call to this callback again, ugly
                                  # so you will need to update the values on another source variable
        print('-- SOURCE DATA AFTER PATCH: {}'.format(source.data))

source.on_change('data', on_change_data_source)

curdoc().add_root(data_table)
    
por ChesuCR 22.03.2018 / 10:15
fonte