【问题标题】:Python 3.x Bokeh - Sort and Update ColumnDataSource After PointDrawToolPython 3.x Bokeh - PointDrawTool 之后对 ColumnDataSource 进行排序和更新
【发布时间】:2020-04-18 03:47:55
【问题描述】:

下面的 python 代码绘制 x,y 并允许在 Bokeh 中使用 PointDrawTool 编辑/添加新点。添加新点时,我想用基于 x 值的线连接所有点。目前,新点添加在末尾,线从原始数据的最后一个点连接到新点。添加新点并重新绘制线后,使用源数据的最佳方法是什么?在我的真实数据中,大小为数百到数千个点。

另外,有没有办法允许在表格中的选定单元格下方插入一个新单元格并添加新数据点,然后更新图形。谢谢。

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))

【问题讨论】:

    标签: python bokeh


    【解决方案1】:

    将此添加到您的代码中:

    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();
        }
    """))
    

    【讨论】:

    • 效果很好。是否可以用不同的颜色保留新点?使用此代码,如果新点 x 值较小,则最后一个点会改变颜色。
    • 原始代码也会发生这种情况。如果您不知道如何解决,请提出一个新问题。
    • 对不起,我不清楚。您的代码在源代码中排序 x,y 但不是颜色。这是一个简单的修复,我很抱歉,因为我对 JS 一无所知。我通过将.map((x, idx) => [x, cb_obj.data.y[idx]]) 更改为.map((x, idx) => [x, cb_obj.data.y[idx], cb_obj.data.color[idx]]) 并在最后一个发出命令之前添加了cb_obj.data.color= acc.map(([, , color]) => color); 来解决这个问题。感谢您的帮助。
    • 需要注意的一点 - 如果您只是单击绘图上的任意位置,它将创建一个新点。它的颜色是黑色的。
    • 是的,在工具中激活 PointDrawTool 时会发生这种情况。
    猜你喜欢
    • 2021-06-04
    • 2020-02-02
    • 1970-01-01
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多