使用 js_on_change 在 Bokeh 中动态更新文本

Update text dynamically in Bokeh with js_on_change

是否可以将 js_on_changebokeh 结合使用来动态更新放置在绘图旁边的文本?

例如,使用来自不同问题的代码片段


from random import random
from bokeh.models import CustomJS, ColumnDataSource, Span
from bokeh.plotting import figure, output_file, show

output_file("callback.html")

x = [random() for x in range(500)]
y = [random() for y in range(500)]
color = ["navy"] * len(x)

s = ColumnDataSource(data=dict(x=x, y=y, color=color))
p = figure(plot_width=400,
           plot_height=400,
           tools="lasso_select",
           title="Select Here")
p.circle(x='x', y='y', color='color', size=8, source=s, alpha=0.4)

slope = Span(location=.5,
             dimension="width",
             line_alpha=.6,
             line_width=5)
p.add_layout(slope)

s.selected.js_on_change(
    'indices',
    CustomJS(args=dict(s=s, slope=slope),
             code="""       
        var inds = cb_obj.indices;
        
        if (inds.length == 0) {
            slope.location = 0.5
            return 
        }
        
        var total = 0;
        for (var i = 0; i < inds.length; i++) {
            total += s.data["y"][inds[i]]
        }
        var avg = total / inds.length;
        slope.location = avg;
    """))

show(p)

我想在图的右侧添加一个文本,显示计算的值 slope.location 并在我 select 新点时更新。

您可以使用像 PreText 这样的文本小部件,将其放在图的右侧 e.g via layout 并更新您的小部件的 .text 属性 JS回调。确保使用 .toString() 方法分配值。

from random import random
from bokeh.models import CustomJS, ColumnDataSource, Span, PreText
from bokeh.plotting import figure, output_file, show
from bokeh.layouts import layout

output_file("callback.html")

x = [random() for x in range(500)]
y = [random() for y in range(500)]
color = ["navy"] * len(x)

s = ColumnDataSource(data=dict(x=x, y=y, color=color))
p = figure(plot_width=400,
           plot_height=400,
           tools="lasso_select",
           title="Select Here")
p.circle(x='x', y='y', color='color', size=8, source=s, alpha=0.4)

slope = Span(location=.5,
             dimension="width",
             line_alpha=.6,
             line_width=5)
p.add_layout(slope)

slope_text = PreText(text='Slope_Text')

s.selected.js_on_change(
    'indices',
    CustomJS(args=dict(s=s, slope=slope, slope_text=slope_text),
             code="""       
        var inds = cb_obj.indices;
        
        if (inds.length == 0) {
            slope.location = 0.5
            return 
        }
        
        var total = 0;
        for (var i = 0; i < inds.length; i++) {
            total += s.data["y"][inds[i]]
        }
        var avg = total / inds.length;
        slope.location = avg;
        slope_text.text = avg.toString();
    """))

layout_ = layout([[p,slope_text]])
show(layout_)