【问题标题】:Bokeh interactive dashboard can not remove lines from plot散景交互式仪表板无法从绘图中删除线条
【发布时间】:2019-08-22 01:27:28
【问题描述】:

我正在开发我的第一个 python Bokeh 交互式仪表板。绘图默认显示 group=a 和 group=b 的行。当复选框 [1] 时,绘图将为 group=a1 和 group=b1 添加行。当取消选中 [1] 时,a1、b1 行应该从绘图中删除,但它们仍然留在绘图中。

以下是我的示例数据和示例代码。它可以直接在你的 jupyter notebook 中运行。谁能帮我吗?非常感谢!

import pandas as pd
import numpy as np
import matplotlib.pylab as plt
from bokeh.io import show, output_notebook, push_notebook
from bokeh.plotting import figure
from bokeh.models import CategoricalColorMapper, HoverTool, ColumnDataSource, Panel
from bokeh.models.widgets import CheckboxGroup, Slider, RangeSlider, Tabs

from bokeh.layouts import column, row, WidgetBox
from bokeh.palettes import Category20_16

from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
from bokeh.palettes import Category10


output_notebook()

data=[['a',1,0],['a',2,1],['a1',1,0],['a1',2,2],['b',1,0],['b',2,3],['b1',1,0],['b1',2,4]]
df=pd.DataFrame(data,columns=['group','time','rate'])


def modify_doc(doc):


    def update(attr,old,new):

        temp=[]
        for i in selection1.active:
            for b in selection2.active:
                temp.append(selection1.labels[i]+selection2.labels[b]   )

        to_plot=temp

        for i in range(len(to_plot)):
            source = ColumnDataSource(
             data={'x':df.loc[df.group == to_plot[i]].time,
                   'group':df.loc[df.group == to_plot[i]].group,
                   'y':df.loc[df.group == to_plot[i]].rate})

            p3.line(x='x',
                    y='y',
                    source=source,
                    legend=to_plot[i],
                     color = (Category10[10])[i])


    selection1=CheckboxGroup(labels=['a','b'],active=[0,1]  )
    selection1.on_change('active',update)   
    selection2=CheckboxGroup(labels=['1'] )
    selection2.on_change('active',update)


    to_plot=['a','b']
    p3 = figure()
    for i in range(len(to_plot)):
        source = ColumnDataSource(
        data={'x':df.loc[df.group == to_plot[i]].time,
                   'group':df.loc[df.group == to_plot[i]].group,
                   'y':df.loc[df.group == to_plot[i]].rate})

        p3.line(x='x',
                    y='y',
                    source=source,
                    legend=to_plot[i],
                    color = (Category10[10])[i])   


    controls=WidgetBox(selection1,selection2)

    layout=row(controls,p3)
    tab=Panel(child=layout,title='test')
    tabs=Tabs(tabs=[tab]) 
    doc.add_root(tabs)

handler=FunctionHandler(modify_doc)
app=Application(handler)

show(app)

【问题讨论】:

    标签: python plot bokeh dashboard interaction


    【解决方案1】:

    很可能,问题(您已经更正了)与此行中的下划线有关:

    temp.append(selection1.labels[i]+ "_" + selection2.labels[b])
    

    当然应该是这样的:

    temp.append(selection1.labels[i] + selection2.labels[b])
    

    所以您在源代码(不存在)中引用了a_1,而不是a1

    如果您取消选中复选框,我可以随意改进您的代码以隐藏行。此代码适用于 Bokeh 服务器 v1.0.4,但在删除标记的行块和取消注释的行后也应适用于 Jupyter Notebook)

    import random
    import pandas as pd
    from tornado.ioloop import IOLoop
    from bokeh.server.server import Server
    from bokeh.application import Application
    from bokeh.application.handlers.function import FunctionHandler
    from bokeh.plotting import figure, ColumnDataSource
    from bokeh.models import CheckboxGroup, Panel, Tabs, WidgetBox, Row
    from bokeh.palettes import Category10
    
    data = [['a', 1, 0], ['a', 2, 1], ['a1', 1, 0], ['a1', 2, 2], ['b', 1, 0], ['b', 2, 3], ['b1', 1, 0], ['b1', 2, 4]]
    df = pd.DataFrame(data, columns = ['group', 'time', 'rate'])
    
    def modify_doc(doc):
        lines = []
    
        def create_plots(to_plot):
            for i in range(len(to_plot)):
                source = ColumnDataSource(
                data = {'x':df.loc[df.group == to_plot[i]].time,
                       'group':df.loc[df.group == to_plot[i]].group,
                       'y':df.loc[df.group == to_plot[i]].rate})
    
                lines.append(p3.line(x = 'x',
                                     y = 'y',
                                     source = source,
                                     legend = to_plot[i],
                                     color = (Category10[10])[i]))
                p3.legend.click_policy = 'hide'
    
        def update(attr, old, new):
            for i in [0, 1]:
                if i not in selection1.active:
                    lines[i].visible = False
                else:
                    lines[i].visible = True
    
            if selection2.active:
                if len(lines) < 3:
                    temp = []
                    for i in selection1.active:
                        lines[i].visible = True
                        for b in selection2.active:
                            temp.append(selection1.labels[i] + selection2.labels[b])
                    create_plots(temp)
                else:
                    for i in range(2, 4):
                        if (i - 2) in selection1.active:
                            lines[i].visible = True
                        else:
                            lines[i].visible = False
            elif len(lines) > 2:
                for i in range(2, 4):
                    if (i - 2) in selection1.active:
                        lines[i].visible = False
    
        selection1 = CheckboxGroup(labels = ['a', 'b'], active = [0, 1], width = 40)
        selection1.on_change('active', update)
        selection2 = CheckboxGroup(labels = ['1'], width = 40)
        selection2.on_change('active', update)
    
        p3 = figure()
        create_plots(['a', 'b'])
    
        controls = WidgetBox(selection1, selection2, width = 40)
        layout = Row(controls, p3)
        tab = Panel(child = layout, title = 'test')
        tabs = Tabs(tabs = [tab])
        doc.add_root(tabs)
    
    # handler = FunctionHandler(modify_doc)
    # app = Application(handler)
    
    #########################################################################
    
    io_loop = IOLoop.current()
    server = Server(applications = {'/myapp': Application(FunctionHandler(modify_doc))}, io_loop = io_loop, port = 5001)
    server.start()
    server.show('/myapp')
    io_loop.start()
    
    #########################################################################
    
    # show(app)
    

    结果:

    【讨论】:

    • 非常感谢!现在可以从图中添加/删除该行(正是我需要的),但图例始终显示'a,b,a1,b1'。能否请您也用线条相应地更改图例?真的很感激!。
    • 我将 p3.legend.click_policy = 'hide' 移动到正确的位置,现在当您取消选中这些框时,图例会静音
    • 谢谢你,托尼!有什么办法可以删除这条线,而不是隐藏它?
    • 官方不支持删除字形。这并非不可能,但对我来说似乎很棘手,因为你很容易把事情搞砸。如果要删除或添加图例,则可以使用 p3.legend[0].items.pop() 和 p3.legend[0].items.append(LegendItem(label = 'label', renderers = [renderer]) ) 但我不会那样做。
    • 如上图所示,如何使用散景仪表板录制游戏?
    猜你喜欢
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 2013-12-14
    • 2012-12-07
    相关资源
    最近更新 更多