猿问

如何定义 Python Bokeh RangeSlider.on_change 回调函数来更改绘图的

我正在尝试为 RangeSlider 实现 python 回调函数。滑块值应该告诉 IndexFilter 应显示哪个索引。


例如:如果 Rangeslider.value 为 (3, 25),我的绘图应仅包含/查看索引从 3 到 25 的数据。


from bokeh.io import output_file, show

from bokeh.models import ColumnDataSource, GMapOptions, CustomJS, CDSView, IndexFilter

from bokeh.plotting import gmap, ColumnDataSource, figure

from bokeh.layouts import column, row

from bokeh.models.widgets import RangeSlider 

import numpy as np


def slider_callback(attr, old, new):

        p.view = CDSView(source=source, filters=[IndexFilter(np.arange(new.value[0], new.value[1]))])

        v.view = CDSView(source=source, filters=[IndexFilter(np.arange(new.value[0], new.value[1]))])



# data set

lon = [[48.7886, 48.7887, 48.7888, 48.7889, 48.789], 

        [48.7876, 48.7877, 48.78878, 48.7879, 48.787], 

        [48.7866, 48.7867, 48.7868, 48.7869, 48.786],

        [48.7856, 48.7857, 48.7858, 48.7859, 48.785],

        [48.7846, 48.7847, 48.7848, 48.7849, 48.784]]

lat = [[8.92, 8.921, 8.922, 8.923, 8.924],

        [8.91, 8.911, 8.912, 8.913, 8.914],

        [8.90, 8.901, 8.902, 8.903, 8.904],

        [8.89, 8.891, 8.892, 8.893, 8.894],

        [8.88, 8.881, 8.882, 8.883, 8.884]]

time = [0, 1, 2, 3, 4, 5]

velocity = [23, 24, 25, 24, 20]

lenght_dataset = len(lon)



# define source and map

source = ColumnDataSource(data = {'x': lon, 'y': lat, 't': time, 'v': velocity})

view = CDSView(source=source, filters=[IndexFilter(np.arange(0, lenght_dataset))])


map_options = GMapOptions(lat=48.7886, lng=8.92, map_type="satellite", zoom=13)


p = gmap("MY_API_KEY", map_options, title="Trajectory Map")

v = figure(plot_width=400, plot_height=400, title="Velocity")



# plot lines on map

p.multi_line('y', 'x', view=view, source=source, line_width=1)

v.line('t', 'v', view=view, source=source, line_width=3)



# slider to limit plotted data

range_slider = RangeSlider(title="Data Range Slider: ", start=0, end=lenght_dataset, value=(0, lenght_dataset), step=1) 


range_slider.on_change('value', slider_callback)




湖上湖
浏览 94回答 1
1回答

开满天机

一些注意事项:time比其余列长 - 您将收到有关它的警告。在下面的代码中,我刚刚删除了它的最后一个元素view一般来说,带有过滤器不应该用于像线条这样的连续字形(v.line特别是 -multi_line很好)。您将收到有关它的警告。但如果 中的索引IndexFilter始终是连续的,那么应该没问题。无论哪种方式,您都可以使用段字形来避免警告在回调中,您尝试设置图形视图 - 视图仅存在于字形渲染器上一般来说,您不想重新创建视图,而是希望重新创建尽可能少的 Bokeh 模型。理想情况下,您只需更改indices过滤器的字段即可。但是 Bokeh 中缺少一些连线,因此您必须设置filters视图的字段,如下所示newPython 回调的参数接收作为第一个参数传递给相应调用的属性的新值on_change。在这种情况下,它将是一个元组,因此new.value[0]您应该使用new[0]由于您已决定使用 Python 回调,因此您不能再使用show和 静态 HTML 文件 - 您必须使用curdoc().add_root和bokeh serve。UI 需要 Python 代码在运行时的某个位置运行更改滑块值时,您会注意到单独的部分multi_line将连接在一起 - 这是一个错误,我刚刚为其创建了https://github.com/bokeh/bokeh/issues/10589这是一个工作示例:from bokeh.io import curdocfrom bokeh.layouts import column, rowfrom bokeh.models import GMapOptions, CDSView, IndexFilterfrom bokeh.models.widgets import RangeSliderfrom bokeh.plotting import gmap, ColumnDataSource, figurelon = [[48.7886, 48.7887, 48.7888, 48.7889, 48.789],       [48.7876, 48.7877, 48.78878, 48.7879, 48.787],       [48.7866, 48.7867, 48.7868, 48.7869, 48.786],       [48.7856, 48.7857, 48.7858, 48.7859, 48.785],       [48.7846, 48.7847, 48.7848, 48.7849, 48.784]]lat = [[8.92, 8.921, 8.922, 8.923, 8.924],       [8.91, 8.911, 8.912, 8.913, 8.914],       [8.90, 8.901, 8.902, 8.903, 8.904],       [8.89, 8.891, 8.892, 8.893, 8.894],       [8.88, 8.881, 8.882, 8.883, 8.884]]time = [0, 1, 2, 3, 4]velocity = [23, 24, 25, 24, 20]lenght_dataset = len(lon)# define source and mapsource = ColumnDataSource(data={'x': lon, 'y': lat, 't': time, 'v': velocity})view = CDSView(source=source, filters=[IndexFilter(list(range(lenght_dataset)))])map_options = GMapOptions(lat=48.7886, lng=8.92, map_type="satellite", zoom=13)p = gmap("API_KEY", map_options, title="Trajectory Map")v = figure(plot_width=400, plot_height=400, title="Velocity")p.multi_line('y', 'x', view=view, source=source, line_width=1)v.line('t', 'v', view=view, source=source, line_width=3)range_slider = RangeSlider(title="Data Range Slider: ", start=0, end=lenght_dataset, value=(0, lenght_dataset), step=1)def slider_callback(attr, old, new):    view.filters = [IndexFilter(list(range(*new)))]range_slider.on_change('value', slider_callback)layout = row(column(p, range_slider), column(v))curdoc().add_root(layout)
随时随地看视频慕课网APP

相关分类

Python
我要回答