使用 rangeslider 创建时间序列图
Create time series graph with rangeslider
我正在尝试创建滑块,当您拖动滑块时,显示的图形部分只是滑块上的部分。例如,如果您查看下面的图表,如果滑块设置为 1990,您将只能看到从 1990 到 2016 的行。我找到了一个 plotly 的工作示例,但我想看看它是否可以完成散景。
到目前为止,这是我的代码:
p = figure(width = 900, height = 450)
p.xaxis.axis_label = 'Year'
p.yaxis.axis_label = 'Aggregated Number of Degrees in Education'
source = ColumnDataSource(df)
fill_source = ColumnDataSource(data=dict(x=[],y=[]))
# Create objects for each line that will be plotted
stem = p.line('year', 'stem', line_color='#8dd3c7', line_width=3, source=source)
stem = p.circle('year', 'stem', line_color='#8dd3c7', line_width=3, source=source)
sped = p.line('year', 'sped', line_color='#fdb462', line_width=3, source=source)
elem = p.line('year', 'elem', line_color='#bebada', line_width=3, source=source)
elem = p.square('year', 'elem', line_color='#bebada', line_width=3, source=source)
other = p.line('year', 'other', line_color='#fb8072', line_width=4, source=source)
aggtotal = p.line('year', 'aggtotal', line_dash=[4,4,], line_color='#80b1d3', line_width=3, source=source)
yaxis = p.select(dict(type=Axis, layout="left"))[0]
yaxis.formatter.use_scientific = False
legend = Legend(items=[("STEM", [stem])
,("SPED" , [sped])
,("Elementary", [elem])
,("Other", [other])
,("Total Education Graduates", [aggtotal])], location=(0, 0))
p.add_tools(HoverTool(tooltips=[("Date", "@year")]))
p.add_layout(legend, 'right')
callback_test = CustomJS(args=dict(source=source,fill_source=fill_source), code="""
var data = source.data;
var fill_data = fill_source.data;
var s_val = cb_obj.value;
fill_data['x']=[];
fill_data['y']=[];
for (i = 0; i < s_val; i++) {
fill_data['y'][i].push(data['y'][i]);
fill_data['x'][i].push(data['x'][i]);
}
fill_source.trigger('change');
""")
sped_slider = Slider(start=1984, end= 2016, value=1, step=1,title="Year",callback=callback_test)
callback_test.args["sped"] = sped_slider
layout = row(p,widgetbox(sped_slider))
这呈现了一个滑块,但它没有做任何事情,我不确定从这里到哪里去。
您的回调代码存在一些问题。例如:
- 你从
0
循环 i
到 s_val
(可能是 1990),这与你的数组长度不一致。
- 您的字形引用了列
'stem'
,等等...但是 fill_source
有列 'x'
和 'y'
- 您的字形参考
source
作为来源,但您更改并触发了 fill_source
上的事件。
所有这些都可能是固定的,但有一个更简单的方法,调整回调中的范围。例如。用这个替换你的回调:
x_range = p.x_range
callback_test = CustomJS(args=dict(x_range=x_range), code="""
var start = cb_obj.value;
x_range.start = start;
x_range.change.emit();
""")
注意事件触发器的变化。您的版本可以使用,但我认为它会被弃用。
还有:
- 这一行
callback_test.args["sped"] = sped_slider
不是必需的
- 您可以在
figure(...)
中添加 toolbar_location='above'
以避免渲染与图例冲突
- 您仍然会在滑块和图例之间遇到布局问题,可以通过不同的方式解决(滑块在下方或将滑块和图例放在
column
中,然后再添加到右侧情节等...)
我正在尝试创建滑块,当您拖动滑块时,显示的图形部分只是滑块上的部分。例如,如果您查看下面的图表,如果滑块设置为 1990,您将只能看到从 1990 到 2016 的行。我找到了一个 plotly 的工作示例,但我想看看它是否可以完成散景。
到目前为止,这是我的代码:
p = figure(width = 900, height = 450)
p.xaxis.axis_label = 'Year'
p.yaxis.axis_label = 'Aggregated Number of Degrees in Education'
source = ColumnDataSource(df)
fill_source = ColumnDataSource(data=dict(x=[],y=[]))
# Create objects for each line that will be plotted
stem = p.line('year', 'stem', line_color='#8dd3c7', line_width=3, source=source)
stem = p.circle('year', 'stem', line_color='#8dd3c7', line_width=3, source=source)
sped = p.line('year', 'sped', line_color='#fdb462', line_width=3, source=source)
elem = p.line('year', 'elem', line_color='#bebada', line_width=3, source=source)
elem = p.square('year', 'elem', line_color='#bebada', line_width=3, source=source)
other = p.line('year', 'other', line_color='#fb8072', line_width=4, source=source)
aggtotal = p.line('year', 'aggtotal', line_dash=[4,4,], line_color='#80b1d3', line_width=3, source=source)
yaxis = p.select(dict(type=Axis, layout="left"))[0]
yaxis.formatter.use_scientific = False
legend = Legend(items=[("STEM", [stem])
,("SPED" , [sped])
,("Elementary", [elem])
,("Other", [other])
,("Total Education Graduates", [aggtotal])], location=(0, 0))
p.add_tools(HoverTool(tooltips=[("Date", "@year")]))
p.add_layout(legend, 'right')
callback_test = CustomJS(args=dict(source=source,fill_source=fill_source), code="""
var data = source.data;
var fill_data = fill_source.data;
var s_val = cb_obj.value;
fill_data['x']=[];
fill_data['y']=[];
for (i = 0; i < s_val; i++) {
fill_data['y'][i].push(data['y'][i]);
fill_data['x'][i].push(data['x'][i]);
}
fill_source.trigger('change');
""")
sped_slider = Slider(start=1984, end= 2016, value=1, step=1,title="Year",callback=callback_test)
callback_test.args["sped"] = sped_slider
layout = row(p,widgetbox(sped_slider))
这呈现了一个滑块,但它没有做任何事情,我不确定从这里到哪里去。
您的回调代码存在一些问题。例如:
- 你从
0
循环i
到s_val
(可能是 1990),这与你的数组长度不一致。 - 您的字形引用了列
'stem'
,等等...但是fill_source
有列'x'
和'y'
- 您的字形参考
source
作为来源,但您更改并触发了fill_source
上的事件。
所有这些都可能是固定的,但有一个更简单的方法,调整回调中的范围。例如。用这个替换你的回调:
x_range = p.x_range
callback_test = CustomJS(args=dict(x_range=x_range), code="""
var start = cb_obj.value;
x_range.start = start;
x_range.change.emit();
""")
注意事件触发器的变化。您的版本可以使用,但我认为它会被弃用。
还有:
- 这一行
callback_test.args["sped"] = sped_slider
不是必需的 - 您可以在
figure(...)
中添加toolbar_location='above'
以避免渲染与图例冲突 - 您仍然会在滑块和图例之间遇到布局问题,可以通过不同的方式解决(滑块在下方或将滑块和图例放在
column
中,然后再添加到右侧情节等...)