在 Bokeh 中使用日期滑块更改数据
Change Data using Date Slider in Bokeh
在 Bokeh 中,我尝试使用滑块更改可视化数据。有趣的是,在滑块更改时,console
会记录预期值,但可视化效果不会按预期更新。
如何获得我想要的功能?
为什么代码记录了正确的数据但图表没有更新?
from bokeh.models import CustomJS, Slider
from bokeh.plotting import ColumnDataSource, figure, output_file, show
from bokeh.embed import file_html
from bokeh.resources import CDN
import pandas as pd
df_str = '''2020-09-10 1 75731 0
2020-09-10 2 71627 0
2020-09-10 3 66972 0
2020-09-10 4 63718 0
2020-09-10 5 61951 0
2020-09-11 1 59380 1
2020-09-11 2 58297 1
2020-09-11 3 57833 1
2020-09-11 4 55669 1
2020-09-11 5 55281 1'''
df = pd.DataFrame([col.split() for col in [row for row in df_str.split('\n')]])
df.columns = ['Date', 'Score', 'ScoreTotal', 'DayNumber']
dates = df.Date.unique()
xs = [[] for _ in range(len(dates))]
ys = [[] for _ in range(len(dates))]
date = [i for i in range(len(dates))]
for _, row in df.iterrows():
i = int(row.DayNumber)
xi = row.Score
yi = row.ScoreTotal
xs[i].append(xi)
ys[i].append(yi)
x = xs[0]
y = ys[0]
xs += [[]] * 3
ys += [[]] * 3
source = ColumnDataSource(data=dict(x=x, y=y, xs=xs, ys=ys))
plot = figure(plot_width=500, plot_height=500)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
date_slider = Slider(start=0, end=2, value=0, step=1, title="Date Slider")
callback = CustomJS(args=dict(source=source, date_slider=date_slider),
code="""
const data = source.data;
const date = date_slider.value
const x = data['xs'][date]
const y = data['ys'][date]
console.log(y) // CORRECT CONSOLE LOG BUT NO CHANGE
source.change.emit();
""")
date_slider.js_on_change('value', callback)
from bokeh.layouts import column, row
layout = row(
plot,
column(date_slider),
)
show(layout)
从 Bokeh Discourse website,我能够让用户解释我的 JS 代码没有修改任何东西,正如 Eugene 在上面的评论中提到的那样。需要就地修改原始数据数组。更新 code
参数导致期望的结果:
code="""
const data = source.data;
const date = date_slider.value;
const old_y = data['y'];
const x = data['xs'][date];
const y = data['ys'][date];
for (var i = 0; i < old_y.length; i++) {
old_y[i] = y[i]
}
source.change.emit();
"""
在 Bokeh 中,我尝试使用滑块更改可视化数据。有趣的是,在滑块更改时,console
会记录预期值,但可视化效果不会按预期更新。
如何获得我想要的功能? 为什么代码记录了正确的数据但图表没有更新?
from bokeh.models import CustomJS, Slider
from bokeh.plotting import ColumnDataSource, figure, output_file, show
from bokeh.embed import file_html
from bokeh.resources import CDN
import pandas as pd
df_str = '''2020-09-10 1 75731 0
2020-09-10 2 71627 0
2020-09-10 3 66972 0
2020-09-10 4 63718 0
2020-09-10 5 61951 0
2020-09-11 1 59380 1
2020-09-11 2 58297 1
2020-09-11 3 57833 1
2020-09-11 4 55669 1
2020-09-11 5 55281 1'''
df = pd.DataFrame([col.split() for col in [row for row in df_str.split('\n')]])
df.columns = ['Date', 'Score', 'ScoreTotal', 'DayNumber']
dates = df.Date.unique()
xs = [[] for _ in range(len(dates))]
ys = [[] for _ in range(len(dates))]
date = [i for i in range(len(dates))]
for _, row in df.iterrows():
i = int(row.DayNumber)
xi = row.Score
yi = row.ScoreTotal
xs[i].append(xi)
ys[i].append(yi)
x = xs[0]
y = ys[0]
xs += [[]] * 3
ys += [[]] * 3
source = ColumnDataSource(data=dict(x=x, y=y, xs=xs, ys=ys))
plot = figure(plot_width=500, plot_height=500)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
date_slider = Slider(start=0, end=2, value=0, step=1, title="Date Slider")
callback = CustomJS(args=dict(source=source, date_slider=date_slider),
code="""
const data = source.data;
const date = date_slider.value
const x = data['xs'][date]
const y = data['ys'][date]
console.log(y) // CORRECT CONSOLE LOG BUT NO CHANGE
source.change.emit();
""")
date_slider.js_on_change('value', callback)
from bokeh.layouts import column, row
layout = row(
plot,
column(date_slider),
)
show(layout)
从 Bokeh Discourse website,我能够让用户解释我的 JS 代码没有修改任何东西,正如 Eugene 在上面的评论中提到的那样。需要就地修改原始数据数组。更新 code
参数导致期望的结果:
code="""
const data = source.data;
const date = date_slider.value;
const old_y = data['y'];
const x = data['xs'][date];
const y = data['ys'][date];
for (var i = 0; i < old_y.length; i++) {
old_y[i] = y[i]
}
source.change.emit();
"""