Я использовал предыдущие посты здесь и здесь , чтобы попытаться выполнить код, с помощью которого я могу выбрать строку в DataTable в Bokeh и получить номер строки.Тем не менее, я обнаружил, что, используя этот код, как только я пройду 6 или 7 строку, сгенерированный номер строки будет неправильным - например, я могу щелкнуть строку 17, и она скажет, что это строка 6. Как мне решить эту проблему?
Примечание: для кода в этом сообщении ошибка возникает только после увеличения диапазона в «исходном» столбце ColourDataSource с 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)