【问题标题】:Changing source of plot in bokeh with a callback使用回调更改散景中的绘图源
【发布时间】:2017-04-05 12:56:16
【问题描述】:

假设我有 2 个(或更多)具有相同列数和行数的数据源:

#Data
dates = [date(2016, i, 1) for i in range(1,13)]

data1 = pd.DataFrame(index = dates, data = random.randn(12, 2),
                     columns = ['A', 'B'])

data2 = pd.DataFrame(index = dates, data = random.randn(12, 2),
                     columns = ['A', 'B'])

我想在散景中绘制列 A 和 B:

#Bokeh
source = ColumnDataSource(source1)
source1 = ColumnDataSource(data1)
source2 = ColumnDataSource(data2)

p = figure(x_axis_type = 'datetime')
l1 = p.line(source = source, x = dates, y= 'A', color = 'Red')
l2 = p.line(source = source, x = dates, y= 'B', color = 'Blue')

我有一个下拉列表:

select = Select(options = ['source1', 'source2'], value = 'source1')

select 创建回调以便折线图中的数据源随着下拉列表中选择的不同选项而改变的最简单方法是什么?我在 JS 方面几乎没有经验,也无法真正理解回调,因此我们将不胜感激。

编辑:

我试过了:

codes = """
var f = cb_obj.get('value');
var sdata = source.data;
var 1data = source1.data;
var 2data = source2.data;

if (f == "source1") {
sdata = 1data ;
source.trigger('change');
};

if (f == "source2") {
sdata = 2data ;
source.trigger('change');
};


"""

select.callback= CustomJS(args= dict(source = source, source1=source1,
                          source2=source2), code = codes)

但它不起作用......

【问题讨论】:

    标签: javascript python bokeh


    【解决方案1】:

    编辑: obj.trigger('change',arg) 已针对散景 0.12.6 进行了更改,现已弃用,新语法为 obj.change.emit(arg),请参阅 Bokeh releases

    您可以清空您的“源”数据列,然后使用 .push() 在 for 循环中重新填充它们

    另外你不应该使用以数字开头的变量名

    codes = """
    var f = cb_obj.get('value');
    var sdata = source.data;
    var data1 = source1.data;
    var data2 = source2.data;
    
    if (f == "source1") {
    sdata["A"] = [] ;
    for (i=0;i<data1["A"].length; i++) {
    sdata["A"].push(data1["A"][i]);
    }
    sdata["B"] = [] ;
    for (i=0;i<data1["B"].length; i++) {
    sdata["B"].push(data1["B"][i]);
    }
    source.trigger('change');
    };
    
    if (f == "source2") {
    sdata["A"] = [] ;
    for (i=0;i<data2["A"].length; i++) {
    sdata["A"].push(data2["A"][i]);
    }
    sdata["B"] = [] ;
    for (i=0;i<data2["B"].length; i++) {
    sdata["B"].push(data2["B"][i]);
    }
    source.trigger('change');
    };
    """
    

    编辑回答评论

    from bokeh.plotting import figure, output_file
    from bokeh.models import CustomJS, ColumnDataSource, Select
    from bokeh.layouts import gridplot
    from bokeh.resources import CDN
    from bokeh.embed import file_html
    
    from random import random
    
    key_list = list('ABCDEFGHIJKLMNOP')
    
    DATA1 = {key:[random() for i in range(10)] for key in key_list}
    DATA2 = {key:[random() for i in range(10)] for key in key_list}
    DATA1['xaxis'] = range(10)
    DATA2['xaxis'] = range(10)
    
    source1 = ColumnDataSource(data=DATA1)
    source2 = ColumnDataSource(data=DATA2)
    
    fill_source = ColumnDataSource(data=DATA1)
    
    fig = figure()
    
    for key in key_list:
        fig.line(x='xaxis',y=key,source=fill_source)
    
    select = Select(options=['source1','source2'],value='source1')
    
    codes = """
    var f = cb_obj.value;
    var sdata = source.data;
    var data1 = source1.data;
    var data2 = source2.data;
    
    console.log(data2);
    
    for (key in data1) {console.log(key);}
    
    if (f == "source1") {
    for (key in data1) {
        sdata[key] = [];
        for (i=0;i<data1[key].length;i++){
        sdata[key].push(data1[key][i]);
        }
    }
    } else {
    for (key in data2) {
        sdata[key] = [];
        for (i=0;i<data2[key].length;i++){
        sdata[key].push(data2[key][i]);
        }
    }
    };
    
    source.trigger("change");
    """
    select.callback = CustomJS(args=dict(source=fill_source,source1=source1,source2=source2),code=codes)
    
    grid = gridplot([[select],[fig]])
    
    outfile=open('select.html','w')
    outfile.write(file_html(grid,CDN,'select'))
    outfile.close()
    

    console.log() 行不是必需的,但您可以使用它来帮助自己理解/调试回调,这些是浏览器控制台中的打印语句(右键单击 -> 检查 -> 控制台)

    【讨论】:

    • 谢谢@Seb,这很好用。我的实际数据源有超过 10 列,您能想到任何简化代码的方法吗?还是必须逐列?再次感谢
    • 我假设每一列都有一行,你可以遍历字典键,我用示例代码编辑了我的答案
    • 完美。非常感谢@Seb
    • 请更新:source.trigger("change") 已弃用。请改用source.change.emit()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2016-01-04
    • 1970-01-01
    相关资源
    最近更新 更多