Bokeh, lasso select to table update

可紊 提交于 2019-12-02 05:55:19

问题


I hope everyone is doing well.

I am trying to develop a Bokeh interaction whereby selecting a part of a scatter plot will update a table.

I am using a lot of the sample code from the Bokeh documentation. My workplace is running an older version of Bokeh (0.12.5) so I had to change the last line in the Custom JS (from s2.change.emit() to s2.trigger('change). I then added in a few lines to create a DataTable.

I naively thought that since sourcing 's1' in the Datatable works, sourcing 's2' will allow me to link the table to the lasso select. I even tried adding in an extra trigger to the table widget in the JS callback.

Does anyone know how to create a table from a lasso select in a graph?

Code

Thanks in advance.

from random import random

from bokeh.layouts import row
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import figure, output_file, show
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn

output_file("callback.html")

x = [random() for x in range(500)]
y = [random() for y in range(500)]

s1 = ColumnDataSource(data=dict(x=x, y=y))
p1 = figure(plot_width=400, plot_height=400, tools="lasso_select", title="Select Here")
p1.circle('x', 'y', source=s1, alpha=0.6)

s2 = ColumnDataSource(data=dict(x=[], y=[]))
p2 = figure(plot_width=400, plot_height=400, x_range=(0, 1), y_range=(0, 1),
            tools="", title="Watch Here")
p2.circle('x', 'y', source=s2, alpha=0.6)

###New code##
columns = [TableColumn(field ="x",  title = "X axis"),
           TableColumn(field ="y",  title = "Y axis")]

table = DataTable(source =s2, columns = columns, width =400, height =  280)


##Added in table.trigger('change') hoping this would link to the lasso select.
s1.callback = CustomJS(args=dict(s2=s2), code="""
        var inds = cb_obj.selected['1d'].indices;
        var d1 = cb_obj.data;
        var d2 = s2.data;
        d2['x'] = []
        d2['y'] = []
        for (i = 0; i < inds.length; i++) {
            d2['x'].push(d1['x'][inds[i]])
            d2['y'].push(d1['y'][inds[i]])
               }
        s2.trigger('change');
        table.trigger('change');
    """)


##having 'table' in the layout, stops the callback from working, deleting table from the layout makes it work.
layout = row(p1, p2, table)

show(layout)

回答1:


Here's a working version for bokeh 1.0.4

from random import random

import bokeh.io
from bokeh.io import output_notebook, show

from bokeh.layouts import row
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import figure
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn

from bokeh.resources import INLINE
bokeh.io.output_notebook(INLINE)

x = [random() for x in range(500)]
y = [random() for y in range(500)]

s1 = ColumnDataSource(data=dict(x=x, y=y))
p1 = figure(plot_width=400, plot_height=400, tools="lasso_select", title="Select Here")
p1.circle('x', 'y', source=s1, alpha=0.6)

s2 = ColumnDataSource(data=dict(x=[], y=[]))
p2 = figure(plot_width=400, plot_height=400, x_range=(0, 1), y_range=(0, 1),
            tools="", title="Watch Here")
p2.circle('x', 'y', source=s2, alpha=0.6)

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

table = DataTable(source =s2, columns = columns, width =155, height = 380)


s1.selected.js_on_change('indices', CustomJS(args=dict(s1=s1, s2=s2, table=table), code="""
        var inds = cb_obj.indices;
        var d1 = s1.data;
        var d2 = s2.data;
        d2['x'] = []
        d2['y'] = []
        for (var i = 0; i < inds.length; i++) {
            d2['x'].push(d1['x'][inds[i]])
            d2['y'].push(d1['y'][inds[i]])
        }
        s2.change.emit();
        table.change.emit();
    """)
)

layout = row(p1, p2, table)

show(layout)

You can even select rows/values in the table and the points in the second plot will change opacity (and you can sort the table by clicking the headers)




回答2:


Right now, your callback doesn't know, what "table" is. You need to pass it as an argument to your CustomJS function:

s1.callback = CustomJS(args=dict(s2=s2, table=table), code="""
    var inds = cb_obj.selected['1d'].indices;
    var d1 = cb_obj.data;
    var d2 = s2.data;
    d2['x'] = []
    d2['y'] = []
    for (i = 0; i < inds.length; i++) {
        d2['x'].push(d1['x'][inds[i]])
        d2['y'].push(d1['y'][inds[i]])
           }
    s2.trigger('change');
    table.trigger('change');
""")


来源:https://stackoverflow.com/questions/48982260/bokeh-lasso-select-to-table-update

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!