【问题标题】:Bokeh Plot Update Using Slider使用滑块更新散景图
【发布时间】:2017-04-24 04:34:16
【问题描述】:

我正在尝试使用滑块来更新我的散景图。我发现使用 pandas 数据框很难实现它(到目前为止没有找到任何示例)。 另一种方法是使用“columndatasource”(在论坛上找到了一些示例)但仍然无法实现该功能。 所以我有两列,X 轴是日期,Y 轴是音量。我想根据滑块输入更改我的 Y 值。我可以看到绘图,但滑块功能不起作用

任何帮助都会非常显着。

source = ColumnDataSource(data=dict(x=df2['Date'],y=df2['Vol']))
S1 = figure(plot_width=400,plot_height=400,tools=TOOLS1,title="Volume Per Day",x_axis_type="datetime")
S1.line('x','y',source=source)

callback_test = CustomJS(args=dict(source=source), code="""
var data = source.get('data');
var s_val = cb_obj.value
x = data['x']
y = data['y']
console.log(cb_obj) 
for (i = 0; i < s_val; i++) {
    y[i] = y[i]            
    }
source.trigger('change');
""")

slider = Slider(start=0, end= max_Vol, value=1, step=100,title="Vol Per Day",callback=callback_test)

【问题讨论】:

  • i 从 0 到 s_val,你只是自己替换了每个 y[i],所以没有任何变化。
  • @Seb ,知道如何实现它..
  • 在您的帖子中,您说“我想根据滑块输入更改 Y 值。”,您究竟希望 Y 值如何变化?
  • 根据滑块值选择数据框的“Vol”列。例如如果 y= 4000 则选择 df2[vol]

标签: python bokeh


【解决方案1】:

您正在尝试更新使用滑块绘制的数据范围。

当你这样做时:

y = data['y']
for (i = 0; i < s_val; i++) {
    y[i] = y[i]            
    }

如果 y 是某个长度为>s_val:

的数组,则相当于 python
for i in range(s_val):
    y[i] = y[i]

这只是自己替换从 0 到 s_val-1 的元素,不会改变列表的其余部分。

你可以做两件事:

  • 直接更新显示的轴范围
  • 使用您将根据滑块值从现有源中填充的空源

.

source = ColumnDataSource(data=dict(x=df2['Date'],y=df2['Vol']))
fill_source = ColumnDataSource(data=dict(x=[],y=[]))
S1 = figure(plot_width=400,plot_height=400,tools=TOOLS1,title="Volume Per Day",x_axis_type="datetime")
S1.line('x','y',source=fill_source)

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');
""")

【讨论】:

    【解决方案2】:

    这是我为使其与 Bokeh 最新版本

    一起工作所做的更改

    JavaScript 部分中的一些语法错误已得到纠正,trigger 更改的方法现在为change.emit,并且在 Slider 之后设置了独立文档的回调 定义感谢js_on_change

    我已经添加了所有的import 命令来给出一个完整的例子 我还更改了可视化以仅显示低于滑块设置的飞行次数的数据(以便在将滑块移向较低值时更容易理解)

    下面是生成的代码:

    from bokeh.layouts import column, widgetbox
    from bokeh.models import ColumnDataSource, CustomJS
    from bokeh.models.widgets import Slider
    from bokeh.plotting import Figure
    import pandas as pd
    from datetime import datetime, date, timedelta
    from bokeh.plotting import show
    from random import randint
    
    today = date.today()
    random_data = [[today + timedelta(days = i), randint(0, 10000)] for i in range(10)]
    df2 = pd.DataFrame(random_data, columns = ['Date', 'Vol'])
    
    source = ColumnDataSource(data = dict(x = df2['Date'], y = df2['Vol']))
    fill_source = ColumnDataSource(data = dict(x = df2['Date'], y = df2['Vol'])) # set the graph to show all data at loading
    TOOLS1 = []
    S1 = Figure(plot_width = 400, plot_height = 400, tools = TOOLS1, title = "Volume Per Day", x_axis_type = "datetime")
    S1.line('x', 'y', source = fill_source)
    
    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 (var i = 0; i <= data.x.length; i++) {   // added "var" declaration of variable "i"
            if (data['y'][i] <= s_val) { // more meaningful visualization: assuming you want to focuss on dates with less number of flights
                fill_data['y'].push(data['y'][i]); // [i] index on left side of assignment removed
            }
            else {
                fill_data['y'].push(0);
            }
            fill_data['x'].push(data['x'][i]);
        }
        fill_source.change.emit() ; // "trigger" method replaced by "change.emit"
    """)
    
    max_Vol = df2['Vol'].max()
    slider = Slider(start = 0, end = max_Vol, value = max_Vol, step = 100, title = "Vol Per Day") # Remove attribute "callback = callback_test"
    slider.js_on_change('value', callback_test) # new way of defining event listener
    
    controls = widgetbox(slider)
    layout = column(controls, S1)
    show(layout)
    

    如果我可以将生成的 (HTML) 可视化直接嵌入到这个答案中,那就太好了,如果可能的话,现在让我 ;)

    【讨论】:

      猜你喜欢
      • 2020-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-22
      • 2019-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多