Python 3.x Bokeh - 在 PointDrawTool 之后排序和更新 ColumnDataSource
Python 3.x Bokeh - Sort and Update ColumnDataSource After PointDrawTool
下面的 python 代码绘制 x,y 并允许 edit/add 在 Bokeh 中使用 PointDrawTool 新点。添加新点时,我想用基于 x 值的线连接所有点。当前,新点添加在末尾,线从原始数据的最后一个点连接到新数据。在添加新点并重画线后,对源数据进行重新排序的最佳方法是什么?在我的真实数据中,大小是几百到几千点。
另外,有没有办法允许在 table 中选定的单元格下方插入一个新单元格并添加新数据点然后更新图形。谢谢
from bokeh.plotting import Column, ColumnDataSource, figure, output_file, show
from bokeh.models import DataTable, TableColumn, PointDrawTool, ColumnDataSource
x=[1, 2, 3, 4, 5, 6, 7, 8]
y=[1,2,1,2,1,2,3,1]
data = {'x': x,
'y': y,
'color': ['blue']*len(x)}
source = ColumnDataSource(data=data)
p = figure(plot_width=400, plot_height=400)
p.line('x', 'y', line_width=2, source=source)
xyp = p.scatter(x='x', y='y', source=source, color='color', size=10)
columns = [TableColumn(field="x", title="x"),
TableColumn(field="y", title="y"),
TableColumn(field='color', title='color')]
table = DataTable(source=source, columns=columns, editable=True, height=200)
draw_tool = PointDrawTool(renderers=[xyp], empty_value='black')
p.add_tools(draw_tool)
p.toolbar.active_tap = draw_tool
show(Column(p, table))
将此添加到您的代码中:
from bokeh.models import CustomJS
source.js_on_change('data', CustomJS(code="""\
let prev_x = null;
let sorted = true;
for (const x of cb_obj.data.x) {
if (prev_x !== null && prev_x > x) {
sorted = false;
break;
}
prev_x = x;
}
if (!sorted) {
const acc = (cb_obj.data.x
.map((x, idx) => [x, cb_obj.data.y[idx]])
.sort(([x1], [x2]) => x1 - x2));
cb_obj.data.x = acc.map(([x]) => x);
cb_obj.data.y = acc.map(([, y]) => y);
cb_obj.change.emit();
}
"""))
下面的 python 代码绘制 x,y 并允许 edit/add 在 Bokeh 中使用 PointDrawTool 新点。添加新点时,我想用基于 x 值的线连接所有点。当前,新点添加在末尾,线从原始数据的最后一个点连接到新数据。在添加新点并重画线后,对源数据进行重新排序的最佳方法是什么?在我的真实数据中,大小是几百到几千点。
另外,有没有办法允许在 table 中选定的单元格下方插入一个新单元格并添加新数据点然后更新图形。谢谢
from bokeh.plotting import Column, ColumnDataSource, figure, output_file, show
from bokeh.models import DataTable, TableColumn, PointDrawTool, ColumnDataSource
x=[1, 2, 3, 4, 5, 6, 7, 8]
y=[1,2,1,2,1,2,3,1]
data = {'x': x,
'y': y,
'color': ['blue']*len(x)}
source = ColumnDataSource(data=data)
p = figure(plot_width=400, plot_height=400)
p.line('x', 'y', line_width=2, source=source)
xyp = p.scatter(x='x', y='y', source=source, color='color', size=10)
columns = [TableColumn(field="x", title="x"),
TableColumn(field="y", title="y"),
TableColumn(field='color', title='color')]
table = DataTable(source=source, columns=columns, editable=True, height=200)
draw_tool = PointDrawTool(renderers=[xyp], empty_value='black')
p.add_tools(draw_tool)
p.toolbar.active_tap = draw_tool
show(Column(p, table))
将此添加到您的代码中:
from bokeh.models import CustomJS
source.js_on_change('data', CustomJS(code="""\
let prev_x = null;
let sorted = true;
for (const x of cb_obj.data.x) {
if (prev_x !== null && prev_x > x) {
sorted = false;
break;
}
prev_x = x;
}
if (!sorted) {
const acc = (cb_obj.data.x
.map((x, idx) => [x, cb_obj.data.y[idx]])
.sort(([x1], [x2]) => x1 - x2));
cb_obj.data.x = acc.map(([x]) => x);
cb_obj.data.y = acc.map(([, y]) => y);
cb_obj.change.emit();
}
"""))