Python 使用RangeSloider创建时间序列图

Python 使用RangeSloider创建时间序列图,python,bokeh,Python,Bokeh,我试图创建一个滑块,当你拖动滑块时,显示的图形部分只是滑块上的部分。例如,如果您查看下面的图表,如果滑块设置为1990,您将只看到从1990年到2016年的线条。我找到了一个与Bokeh一起工作的示例,但我想看看它是否可以与Bokeh一起完成。 这是我目前的代码: p = figure(width = 900, height = 450) p.xaxis.axis_label = 'Year' p.yaxis.axis_label = 'Aggregated Number of Degrees

我试图创建一个滑块,当你拖动滑块时,显示的图形部分只是滑块上的部分。例如,如果您查看下面的图表,如果滑块设置为1990,您将只看到从1990年到2016年的线条。我找到了一个与Bokeh一起工作的示例,但我想看看它是否可以与Bokeh一起完成。

这是我目前的代码:

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))

这渲染了一个滑块,但它没有做任何事情,我不知道从这里去哪里

您的回调代码存在一些问题。例如:

您将i从0循环到s_val,这可能是1990,这与数组的长度不一致。 您的图示符引用列“干”等。。。但是fill_源有“x”和“y”列 您的标志符号引用源作为源,但您更改并触发了填充源上的事件。 所有这些都可能被修复,但有一种更简单的方法,调整回调中的范围。例如,将您的回拨替换为以下内容:

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();
""")
注意对事件触发器的更改。你的版本可以工作,但我认为它将被弃用

此外:

此行回调\u test.args[sped]=sped\u滑块不是必需的 您可以在图中添加工具栏\u location='over'。。。避免渲染与图例冲突的步骤 滑块和图例之间仍然存在布局问题,可以通过不同的方式将其固定在滑块下方,或者在添加到绘图右侧之前将滑块和图例放置在列中,等等。。。
您的回调代码存在一些问题。例如:

您将i从0循环到s_val,这可能是1990,这与数组的长度不一致。 您的图示符引用列“干”等。。。但是fill_源有“x”和“y”列 您的标志符号引用源作为源,但您更改并触发了填充源上的事件。 所有这些都可能被修复,但有一种更简单的方法,调整回调中的范围。例如,将您的回拨替换为以下内容:

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();
""")
注意对事件触发器的更改。你的版本可以工作,但我认为它将被弃用

此外:

此行回调\u test.args[sped]=sped\u滑块不是必需的 您可以在图中添加工具栏\u location='over'。。。避免渲染与图例冲突的步骤 滑块和图例之间仍然存在布局问题,可以通过不同的方式将其固定在滑块下方,或者在添加到绘图右侧之前将滑块和图例放置在列中,等等。。。