使用on_change回调,我可以在Bokeh中获取DataTable中所选内容的数字行索引。是否可以:a)获取列索引b)获取索引值(列标题和行标题)
示例代码:
from bokeh.io import curdoc from bokeh.layouts import row, column import pandas as pd from bokeh.models import ColumnDataSource, ColorBar, DataTable, DateFormatter, TableColumn, HoverTool, Spacer, DatetimeTickFormatter ''' Pandas ''' df = pd.DataFrame(data = {'Apples': [5,10], 'Bananas': [16,15], 'Oranges': [6,4]}) df.rename(index={0:'A',1:'B'}, inplace=True) ''' BOKEH ''' sourceTableSummary = ColumnDataSource(df) Columns = [TableColumn(field=colIndex, title=colIndex) for colIndex in df.columns] data_table = DataTable(columns=Columns, source=sourceTableSummary, index_position = 0, width = 1900, height = 200, fit_columns=False) ''' Funcs ''' def return_value(attr, old, new): selectionRowIndex=sourceTableSummary.selected.indices[0] print("Selected Row Index ", str(selectionRowIndex)) selectionValue=sourceTableSummary.data['Apples'][selectionRowIndex] print("Selected value for Apples ", str(selectionValue)) # selectionColumnIndex? # selectionRowHeader? # selectionColumnHeader? sourceTableSummary.on_change('selected', return_value) curdoc().add_root(column(children=[data_table]))
这给出了以下内容,它们可以返回行以及选择中的值。如果我总是希望返回单个列,则这是理想的。但是,选择UI(虚线)似乎表明特定的列是已知的,而不仅仅是行。如果无法获得选定的列,我可以同时使用行索引和单元格值来查找它吗?
本地服务器输出和表
以下代码使用JS回调显示行索引和列索引以及单元格内容。第二个Python回调是重设索引的技巧,以便可以检测到对同一行的单击(已使用Bokeh v1.0.4进行了测试)。与运行bokeh serve --show app.py
bokeh serve --show app.py
from random import randint from datetime import date from bokeh.models import ColumnDataSource, TableColumn, DateFormatter, DataTable, CustomJS from bokeh.layouts import column from bokeh.models.widgets import TextInput from bokeh.plotting import 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) text_row = TextInput(value = None, title = "Row index:", width = 420) text_column = TextInput(value = None, title = "Column Index:", width = 420) text_date = TextInput(value = None, title = "Date:", width = 420) text_downloads = TextInput(value = None, title = "Downloads:", width = 420) test_cell = TextInput(value = None, title = "Cell Contents:", width = 420) 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 } } } text_row.value = String(row); text_column.value = String(column); text_date.value = String(new Date(source.data['dates'][row])); text_downloads.value = String(source.data['downloads'][row]); test_cell.value = column == 1 ? text_date.value : text_downloads.value; """ def py_callback(attr, old, new): source.selected.update(indices = []) source.selected.on_change('indices', py_callback) callback = CustomJS(args = dict(source = source, text_row = text_row, text_column = text_column, text_date = text_date, text_downloads = text_downloads, test_cell = test_cell), code = source_code) source.selected.js_on_change('indices', callback) curdoc().add_root(column(data_table, text_row, text_column, text_date, text_downloads, test_cell))
结果: