使用Bokeh中的复选框小部件隐藏或显示动态行数的行

时间:2018-03-09 23:49:54

标签: javascript python python-2.7 bokeh

我正在尝试在散景图中添加复选框,以便我可以在我的情节中隐藏或显示不同的线条。我从github找到了一些代码并修改它以实现我的目的。请查看以下代码,

    for data, name, color in zip([AAPL, IBM, MSFT, GOOG], ["AAPL", "IBM", "MSFT", "GOOG"], Spectral4):          
        df = pd.DataFrame(data) 
        source = ColumnDataSource(data = dict(date = pd.to_datetime(df['date']), close = df['close']))                      
        plt = fig.line('date', 'close', line_width=2, color=color, alpha=0.8,
               muted_color=color, muted_alpha=0.2, legend = name, source=source)

        graph_labels.append(name)
        plots.append(plt)

    checkbox = CheckboxGroup(labels = graph_labels, active = [0,1,2,3]) 

    checkbox.callback = CustomJS(args = dict(line0 = plots[0], line1=plots[1], line2=plots[2], line3=plots[3]),  code=""" 
        //console.log(cb_obj.active);
        line0.visible = false;
        line1.visible = false;
        line2.visible = false;
        line3.visible = false;

        for (i in cb_obj.active) {
            //console.log(cb_obj.active[i]);
            if (cb_obj.active[i] == 0) {
                line0.visible = true;
            } else if (cb_obj.active[i] == 1) {
                line1.visible = true;
            } else if (cb_obj.active[i] == 2) {
                line2.visible = true;
            } else if (cb_obj.active[i] == 3) {
                line3.visible = true;
            }
        }
    """)

    layout = row(fig, widgetbox(checkbox), sizing_mode='fixed')

    show(layout)     

此代码完美无缺。然而,我的要求是别的。在我的情况下,每次运行代码时,plts的数量都会不同,因为我的数据不同。所以我试图修改这段代码,但还没有取得任何成功。

我所做的更改是

    checkbox = CheckboxGroup(labels = graph_labels, active = list(range(0, len(plots))))
    arg_list = []

    for idx in range(0, len(plots)):
        arg_list.append('line' + str(idx))
        arg_list.append(plots[idx])

    i = iter(arg_list)  
    checkbox.callback = CustomJS(args = dict(izip(i, i)),  code=""" 
        // Here I don't know how to use dynamic names for line0 and line1 and use them to control their visibility
        // As type of line0 is object and if I 'm trying to make a dynamic string I can't convert it to object and it fails

我也尝试过使用

    source = ColumnDataSource(data = dict( ... ) ...
    callback = CustomJS(args=dict(source=source), code="""

但它也失败了,并没有显示任何情节。 我使用的是最新版本的Bokeh和python 2.7 任何建议都是高度赞赏的,并提前感谢!! :)

2 个答案:

答案 0 :(得分:0)

您可以这样做:

from bokeh.io import show
from bokeh.plotting import figure
from bokeh.models import CustomJS, CheckboxGroup
from bokeh.layouts import Row
from bokeh.palettes import Category20_20

from random import random,choice

N_lines = int(100*random())/10 # undefined but known from the start number of lines.

x= range(3)
fig = figure()
args = []
code = "active = cb_obj.active;"
for i in range(N_lines):
    glyph = fig.line(x,[random() for j in x],color=choice(Category20_20))
    args += [('glyph'+str(i),glyph)]
    code += "glyph{}.visible = active.includes({});".format(i,i)

checkbox = CheckboxGroup(labels=[str(i) for i in range(N_lines)],active=range(N_lines))

checkbox.callback = CustomJS(args={key:value for key,value in args},code=code)

show(Row(fig,checkbox))

这将根据行数构建回调代码。 由于您要求代码适应您的数据,您当然可以确定数据中的行数。

之后,如果您还想通过需要更新的交互动态添加行:

checkbox.labels(只需添加一个标签名称)

checkbox.active(将其设置为另一个数字的range()列表)

checkbox.callback(还有一对用于“args”,另外一对用于“代码”)

答案 1 :(得分:-1)

其实我从以下帖子中找到了这个问题的答案

How to interactively display and hide lines in a Bokeh plot?

在评论部分,user2561747提出了类似的建议。最初我遇到了问题,因为我想使用悬停工具,我试图以不同的方式命名每个情节,然后是类似的东西

    for column, color in zip(df.columns.values, Spectral4):
    ...... 
    ...... 
         plt = fig.line('date', 'value', name = column, line_width = 2, color = color, alpha = 0.8,
                   muted_color = color, muted_alpha = 0.2, legend = column, source = source)

         graph_labels.append(column)
         plots.append(plt)
    ......
    ......

    checkbox = CheckboxGroup(labels = graph_labels, active = list(range(0, len(plots))))    

    checkbox.callback = CustomJS.from_coffeescript(args = dict(plot = fig, checkbox = checkbox), code=""" 
    rends = []; 
    rends.push plot.select(label) for label in checkbox.labels;
    rends[i].visible = i in checkbox.active for i in [0...rends.length];
    """)

我永远无法弄清楚问题是什么,但我最终命名所有情节“可隐藏”,它也适用于悬停工具。所以最终的代码看起来像这样,

    checkbox.callback = CustomJS.from_coffeescript(args = dict(plot = fig, checkbox = checkbox), code=""" 
    rends = plot.select("hideable");
    rends[i].visible = i in checkbox.active for i in [0...rends.length];
    """)

如果有人能够通过第一种方法找出问题那就太棒了。我在浏览器控制台中看到绝对没有错误,但是rends数组的元素在两种情况下都有不同的结构。