散景 source.change.emit() 仅适用于第一次更改
Bokeh source.change.emit() only works on first change
我正在尝试创建一个交互式堆叠条形图来显示给定滑块值的数据。整个数据存储在基础数据集中,显示的数据是该基础数据集的子集。我面临的问题是代码基本上可以工作,但只有第一次发出更改。
这是一个最小的例子:
from bokeh.layouts import column
from bokeh.models import CustomJS, Slider
from bokeh.plotting import ColumnDataSource, figure, output_file, show
import pandas as pd
base = pd.DataFrame({'a': [1, 2, 3, 4, 5, 6],
'b': [10, 20, 30, 40, 50, 60],
'c': ['x', 'y', 'x', 'y', 'x', 'y']})
edit = pd.DataFrame({'a': [1, 2],
'b': [10, 20],
'c': ['x', 'y']})
sbase = ColumnDataSource(data=base)
sedit = ColumnDataSource(data=edit)
p = figure(x_range=['x', 'y'], width=200, height=200)
p.vbar_stack(stackers=['a', 'b'], x='c', width=0.9, color=['#7570b3', '#1b9e77'], source=sedit)
slider = Slider(start=1, end=3, value=1, step=1, title='slider')
slider_callback = CustomJS(args=dict(sbase=sbase, sedit=sedit), code="""
const sid = cb_obj.value;
const bs = sbase.data;
const ed = sedit.data;
var ix = sid*2-2;
var iy = sid*2-1;
ed['a'] = [bs['a'][ix], bs['b'][ix]];
ed['b'] = [bs['a'][iy], bs['b'][iy]];
console.log(ed)
console.log(sedit.data)
sedit.change.emit();
console.log(sedit.data)
""")
slider.js_on_change('value', slider_callback)
output_file('test.html')
show(column(p, slider))
我有点不知所措,因为根据日志,基础数据确实随着后续输入而改变,但图表仍然保持冻结状态。
source.change.emit
可能应该是内部的,但在一些地方提到它是目前唯一的选择。但是,通常(包括这种情况)推荐的最佳做法始终是进行真正的分配以立即更新整个 属性 值(例如 .data
),而不是更改内容“in-place ".
slider_callback = CustomJS(args=dict(sbase=sbase, sedit=sedit), code="""
const sid = cb_obj.value;
const bs = sbase.data;
const ix = sid*2-2;
const iy = sid*2-1;
sedit.data = {
a: [bs['a'][ix], bs['b'][ix]],
b: [bs['a'][iy], bs['b'][iy]],
c: bs.c
}
""")
我正在尝试创建一个交互式堆叠条形图来显示给定滑块值的数据。整个数据存储在基础数据集中,显示的数据是该基础数据集的子集。我面临的问题是代码基本上可以工作,但只有第一次发出更改。
这是一个最小的例子:
from bokeh.layouts import column
from bokeh.models import CustomJS, Slider
from bokeh.plotting import ColumnDataSource, figure, output_file, show
import pandas as pd
base = pd.DataFrame({'a': [1, 2, 3, 4, 5, 6],
'b': [10, 20, 30, 40, 50, 60],
'c': ['x', 'y', 'x', 'y', 'x', 'y']})
edit = pd.DataFrame({'a': [1, 2],
'b': [10, 20],
'c': ['x', 'y']})
sbase = ColumnDataSource(data=base)
sedit = ColumnDataSource(data=edit)
p = figure(x_range=['x', 'y'], width=200, height=200)
p.vbar_stack(stackers=['a', 'b'], x='c', width=0.9, color=['#7570b3', '#1b9e77'], source=sedit)
slider = Slider(start=1, end=3, value=1, step=1, title='slider')
slider_callback = CustomJS(args=dict(sbase=sbase, sedit=sedit), code="""
const sid = cb_obj.value;
const bs = sbase.data;
const ed = sedit.data;
var ix = sid*2-2;
var iy = sid*2-1;
ed['a'] = [bs['a'][ix], bs['b'][ix]];
ed['b'] = [bs['a'][iy], bs['b'][iy]];
console.log(ed)
console.log(sedit.data)
sedit.change.emit();
console.log(sedit.data)
""")
slider.js_on_change('value', slider_callback)
output_file('test.html')
show(column(p, slider))
我有点不知所措,因为根据日志,基础数据确实随着后续输入而改变,但图表仍然保持冻结状态。
source.change.emit
可能应该是内部的,但在一些地方提到它是目前唯一的选择。但是,通常(包括这种情况)推荐的最佳做法始终是进行真正的分配以立即更新整个 属性 值(例如 .data
),而不是更改内容“in-place ".
slider_callback = CustomJS(args=dict(sbase=sbase, sedit=sedit), code="""
const sid = cb_obj.value;
const bs = sbase.data;
const ix = sid*2-2;
const iy = sid*2-1;
sedit.data = {
a: [bs['a'][ix], bs['b'][ix]],
b: [bs['a'][iy], bs['b'][iy]],
c: bs.c
}
""")