Python 3.x Bokeh - сортировка и обновление ColumnDataSource после PointDrawTool - PullRequest
0 голосов
/ 18 апреля 2020

Код python ниже отображает x, y и позволяет редактировать / добавлять новые точки с помощью PointDrawTool в Bokeh. При добавлении новых точек я хотел бы соединить все точки линией, основанной на значениях 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))

1 Ответ

0 голосов
/ 18 апреля 2020

Добавьте это к своему коду:

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