javascript - 在 Bokeh DataTable 错误中引用行/列的 JS 代码
问题描述
我在这里和这里使用了以前的帖子来尝试运行代码,借此我可以在 Bokeh 的 DataTable 中选择一行,并获取行号。但是我发现使用该代码,一旦我超过第 6 行或第 7 行,生成的行号是错误的 - 例如,我可以单击第 17 行,它会说它是第 6 行。我该如何解决这个问题?
请注意这篇文章中的代码,只有当我将“源”ColumnDataSource 中的范围从 10 增加到 20 时才会发生错误。
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(20)], downloads = [randint(0, 100) for i in range(20)]))
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):
print(test_cell.value)
print(text_date.value)
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))
我附上了运行代码时遇到的错误的图片。如您所见,我单击了第 16 行,它说的是第 10 行。
或者我的其他代码(引用我已经从本地工作服务器上的数据创建的许多不同的数据框等):
import pandas as pd
pd.options.mode.chained_assignment = None
import datetime as dt
import math
import random
import pandas as pd
import itertools
import pickle
from bokeh.layouts import layout
from collections import OrderedDict
from bokeh.models import ColumnDataSource, Column, TableColumn, DateFormatter, DataTable, CustomJS, DataRange1d
from bokeh.plotting import figure, curdoc
source = ColumnDataSource(dict(products=dfNew['Products'], prices=dfNew['Current Prices']))
columns = [TableColumn(field="products", title="Products"), TableColumn(field="prices", title="Current Prices")]
data_table = DataTable(source=source, columns=columns, width=400, height=350, editable=True, reorderable=False)
location_source = ColumnDataSource(dict(row=[], column=[]))
prodPx = OrderedDict()
pVal = 0
for i in products:
key = str(i)
prodPx[key] = [(dfNew['Current Prices'])[pVal]]
pVal += 1
noProd = OrderedDict()
kVal = 0
for i in products:
key = str(kVal)
noProd[key] = [i]
kVal += 1
prodpx_source = ColumnDataSource(prodPx)
noprod_source = ColumnDataSource(noProd)
#initial chart
x = new_dates
y = df[products[0]]
sourceChart = ColumnDataSource(data=dict(x=x, y=y))
chart = figure(title=ccy + ' Charting', x_axis_type='datetime', plot_width = 1200, plot_height=500)
chart.line('x', 'y', source=sourceChart, line_width=3, line_alpha=0.6)
#callbacks
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]};
}
}
}
source.change.emit();
source2.change.emit();
source3.change.emit();
source4.change.emit();
"""
#js callback
callback = CustomJS(args=dict(source=source, source2=location_source, source3=prodpx_source,
source4=noprod_source), code=source_code)
source.selected.js_on_change('indices', callback)
#python callback
def py_callback(attr, old, new):
row = str((location_source.data['row'][0]))
chartVals = (noprod_source.data[row][0])
try:
yVar = df[chartVals]
except:
yVar = df[totalProducts[0]]
sourceChart.data = dict(x=x, y=yVar)
source.selected.update(indices=[])
print(location_source.data)
source.selected.on_change('indices', py_callback)
layout = layout([data_table], [chart])
curdoc().add_root(layout)
解决方案
我的回调代码不适用于具有滚动条的表。从那时起,我将它更新为更强大的东西(但它仅适用于文档中的第一个表格小部件)
from bokeh.io import show
from bokeh.layouts import widgetbox
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.models.widgets import DataTable,TableColumn
column_list = ['col1','col2','col3']
source = ColumnDataSource(data = {key:range(20) for key in column_list})
columns = [TableColumn(field=col, title=col) for col in column_list]
data_table = DataTable(source=source, columns=columns, width=400, height=280,selectable=True)
source_code = """
var grid = document.getElementsByClassName('grid-canvas')[0];
var active_row = grid.querySelectorAll('.active')[0];
if (active_row!=undefined){
var active_row_ID = Number(active_row.children[0].innerText);
for (var i=1, imax=active_row.children.length; i<imax; i++){
if (active_row.children[i].className.includes('active')){
var active_col_ID = i-1;
}
}
console.log('row',active_row_ID);
console.log('col',active_col_ID);
var active_cells = grid.querySelectorAll('.active');
for (i=0, imax=active_cells.length;i<imax;i++){
active_cells[i].classList.remove('active');
}
cb_obj.indices = [];
}
"""
source.selected.js_on_change('indices', CustomJS(args={'source':source},code= source_code) )
show(widgetbox(data_table))
您可以使用 active_row_ID 和 active_col_ID
cb_obj.indices = []
是否允许在连续两次单击同一单元格时触发回调。但这会再次触发回调。
这就是为什么最后一个循环active_cells
是从活动单元格的类名中删除的原因.active
,这将active_row
在第二次执行中变为未定义。
if (active_row!=undefined)
是否可以丢弃回调的第二次执行。
推荐阅读
- python - 将大型 SQL Server 表导入 Python
- python - 在 python3 上使用 struct.unpack('f', b"".join(map(chr, bytes)))[0] “期望一个类似字节的对象,str found” - 但在 python2 上工作
- firebase - Flutter Firebase中的核心/未初始化
- node.js - 如何使用 Electron-React 应用程序运行外部脚本
- stm32cubeide - 在 STM32CubeIDE 项目中添加新的 .h 和 .cpp 文件的位置
- javascript - Node Express-删除路由有效但抛出错误
- acumatica - 具有选择器属性的新字段
- javascript - React 中的“BigInt 未定义”
- intellij-idea - 如何在 Intellij 中设置 StyleLint 的根目录?
- node.js - 在 Express 和 Mongo 中使用方法填充时出现 500 错误