Chart on click selection from data table in Bokeh

纵饮孤独 提交于 2019-12-31 05:38:05

问题


I've taken the below code from another source - it is not my own code.

The code allows you to select a cell in the data table, and the 'downloads' data for that cell will chart based on the row of the cell selected.

How do I expand this code such that if I have multiple variables (eg. 'downloads' and 'uploads') and so more columns in the data table, I can chart data based on that cell (so where row AND column are important)? Alternatively, how can I define as a variable the column number of a selected cell (in the same way selected_row below can be used to define the row number)?

from datetime import date
from random import randint
from bokeh.models import ColumnDataSource, Column
from bokeh.plotting import figure, curdoc
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn, Div
import numpy as np

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

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

data_table = DataTable(source = d_source, columns = columns, width = 400, height = 280)

def table_select_callback(attr, old, new):
    selected_row = new[0]
    download_count = data['downloads'][selected_row]
    chart_data = np.random.uniform(0, 100, size = download_count)
    p = figure(title = 'bla')
    r = p.line(x = range(len(chart_data)), y = chart_data)
    root_layout.children[1] = p

d_source.selected.on_change('indices', table_select_callback)

root_layout = Column(data_table, Div(text = 'Select Date'))
curdoc().add_root(root_layout)

回答1:


My suggestion is to use my another post that uses a JS callback to access the row and column of the selected cell. This must be a JS callback as it uses HTML elements to walk through. So the steps are as follows:

  1. Define a new ColumnDataSource that will contain the row and column number of a clicked cell

    info_source = ColumnDataSource(dict(row = [], column = []))

  2. Use the JS callback from this post to fill in the row and column values in this new table_info_source like this:

callback=CustomJS(args=dict(source=d_source,source2=info_source),code=source_code)
source.selected.js_on_change('indices', callback)

  1. Inside the JS callback store the row and column index like this:

    source2.data = {row:[row],column:[column]};

  2. Access the info_source.data information in your Python callback to draw a plot

    print (info_source.data)

Both callback are attached to the same source but usually JS callback is executed first so the data should be available in the Python callback on time. Having the index of row and column of the clicked cell you should be able to retrieve the required data and draw your chart.




回答2:


This is the final working code (run from command line with bokeh serve --show app.py):

from datetime import date
from random import randint
from bokeh.models import ColumnDataSource, Column, TableColumn, DateFormatter, DataTable, CustomJS
from bokeh.plotting import figure, curdoc

source = ColumnDataSource(dict(dates = [date(2014, 3, i + 1) for i in range(10)], downloads = [randint(0, 100) for i in range(10)]))
columns = [TableColumn(field = "dates", title = "Date", formatter = DateFormatter()), TableColumn(field = "downloads", title = "Downloads")]
data_table = DataTable(source = source, columns = columns, width = 400, height = 280, editable = True, reorderable = False)
info_source = ColumnDataSource(dict(row = [], column = []))

source_code = """
var grid = document.getElementsByClassName('grid-canvas')[0].children;
var row, column = '';

for (var i = 0,max = grid.length; i < max; i++){
    if (grid[i].outerHTML.includes('active')){
        row = i;
        for (var j = 0, jmax = grid[i].children.length; j < jmax; j++)
            if(grid[i].children[j].outerHTML.includes('active')) {
                column = j; 
                source2.data = {row: [row], column: [column]};
            }
    }
}"""

callback = CustomJS(args = dict(source = source, source2 = info_source), code = source_code)
source.selected.js_on_change('indices', callback)

def py_callback(attr, old, new):
    source.selected.update(indices = [])
    print(info_source.data)

source.selected.on_change('indices', py_callback)
curdoc().add_root(Column(data_table))


来源:https://stackoverflow.com/questions/55964945/chart-on-click-selection-from-data-table-in-bokeh

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