Интерактивная панель Bokeh не может удалить линии из сюжета - PullRequest
0 голосов
/ 01 апреля 2019

Я работаю над своей первой интерактивной панелью Python Bokeh. На графике по умолчанию отображаются строки для group = a и group = b. Когда флажок [1], заговор добавит линии для group = a1 и group = b1. Если снять отметку [1], линии a1, b1 должны быть удалены из графика, но они все еще остаются в графике.

Ниже приведены мои образцы данных и пример кода. Он может работать непосредственно в вашем ноутбуке Jupyter. Может кто-нибудь мне помочь? Большое спасибо!

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)

1 Ответ

1 голос
/ 01 апреля 2019

Скорее всего, проблема (которую вы уже исправили) была с подчеркиванием в этой строке:

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)

Результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...