我正在尝试创建一个散景图,其中使用滑块来更新多个标签。我下面的代码是关于stackoverflow here和here的两个问题的组合。
在代码中,我具有静态的x和y坐标,它只是我要使用滑块操纵的文本标签。下面的代码似乎没有显示甚至更新。为什么不显示和/或更新?
from bokeh.plotting import figure, show, output_file
from bokeh.models import ColumnDataSource, Range1d, LabelSet, Label, Slider, TextInput, CustomJS
from bokeh.layouts import column, row
output_file("image.html")
plot = figure(x_range=(0, 100), y_range=(0, 100))
source = ColumnDataSource(
data=dict(
x=[55, 28, 18, 74, 76, 28, 32, 18, 60, 84, 44, 56, 56, 76],
y=[8, 8, 33, 14, 72, 64, 46, 20, 52, 56, 84, 22, 36, 32],
v1=prices_final["1"].values,
v2=prices_final["2"].values,
v3=prices_final["3"].values,
v4=prices_final["4"].values,
)
)
labels = ColumnDataSource(data=dict(x=[], y=[], t=[], ind=[]))
plot.add_layout(
LabelSet(
x="x",
y="y",
text="t",
source=labels,
level="overlay",
x_offset=0,
y_offset=0,
render_mode="canvas",
text_font_size="10pt",
text_color="black",
background_fill_color="white",
border_line_color="black",
)
)
# Set up widgets
slider = Slider(title="Hour of day", value=1.0, start=1.0, step=1.0, end=24.0)
code = """
labels.data = {'x':[],'y':[],'t':[]}
source.selected.indices = [slider.value]
labels.data = {'ind':[slider.value],
'x':[source.data.x],
'y':[source.data.y],
't':[source.data.v[slider.value]]}
labels.change.emit()
source.change.emit()
"""
callback = CustomJS(args=dict(source=source, slider=slider, labels=labels), code=code)
slider.js_on_change("value", callback)
layout = column(slider, plot)
show(layout)
最终价格看起来像:
prices_final['1'].values = array([ -5.25, 2.67, 10.67, -0.95, -9.54,
-4.22, -5.2 , -5.53, -9.33, -3.49, -0.47, -8.96, -17.88, -5.49])
所有其他prices_final具有相似的数据结构。
编辑:此代码显示了带有滑块和v1,v2,..值作为标签的图形。您需要更改v1,... v4部分。我不能用很多v来写短,所以用24可能会很长。
from bokeh.layouts import row, column
from bokeh.models import CustomJS, Slider, LabelSet
from bokeh.plotting import figure, output_file, show, ColumnDataSource
x = [55, 28, 18, 74, 76, 28, 32, 18, 60, 84, 44, 56, 56, 76]
y = [8, 8, 33, 14, 72, 64, 46, 20, 52, 56, 84, 22, 36, 32]
label_selected = [''] * 14
# To simplify, make v1 to v4 with same num
v1 = [1] * 14
v2 = [2] * 14
v3 = [3] * 14
v4 = [4] * 14
# list of all v1,v2...
v = [v1, v2, v3, v4]
source = ColumnDataSource(
data=dict(x=x, y=y, v=v, label_selected=label_selected)
)
plot = figure(x_range=(0, 100), y_range=(0, 100), plot_width=400, plot_height=400)
plot.circle(x, y, radius=5, fill_color="red", fill_alpha=0.6, line_color=None)
slider = Slider(title="Hour of day", value=1.0, start=1.0, step=1.0, end=24.0)
code = """
const data = source.data;
const A = hour.value; /* hour starts from 1*/
const x = data['x'];
const y = data['y'];
let label_selected = data['label_selected'];
const v1 = data['v'][0];
const v2 = data['v'][1];
const v3 = data['v'][2];
const v4 = data['v'][3];
if (A == 1){
label_list = v1
} else if (A == 2) {
label_list = v2
} else if (A == 3) {
label_list = v3
} else if (A == 4) {
label_list = v4
}
for (var i = 0; i < label_selected.length; i++){
label_selected[i] = label_list[i]
}
source.change.emit();
"""
callback = CustomJS(
args=dict(source=source, hour=slider),
code=code
)
slider.js_on_change("value", callback)
labels = LabelSet(
x="x",
y="y",
text="label_selected",
level="glyph",
x_offset=5,
y_offset=5,
source=source,
render_mode="canvas",
)
plot.add_layout(labels)
layout = row(plot, column(slider))
output_file("slider.html", title="slider.py example")
show(layout)