แดชบอร์ดแบบโต้ตอบ Bokeh ไม่สามารถลบเส้นออกจากโครงเรื่องได้

ฉันกำลังทำงานกับแดชบอร์ดแบบโต้ตอบ 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)

person jean    schedule 31.03.2019    source แหล่งที่มา


คำตอบ (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)

ผลลัพธ์:

ป้อนคำอธิบายรูปภาพที่นี่

person Tony    schedule 01.04.2019
comment
ขอบคุณมาก! ตอนนี้สามารถเพิ่ม/ลบบรรทัดออกจากพล็อตได้ (ตรงกับที่ฉันต้องการ) แต่คำอธิบายจะแสดง 'a, b,a1,b1' เสมอ คุณช่วยทำให้ตำนานเปลี่ยนตามบรรทัดได้ไหม ขอบคุณจริงๆ !. - person jean; 01.04.2019
comment
ฉันย้าย p3.legend.click_policy = 'hide' ไปยังตำแหน่งที่ถูกต้อง และตอนนี้คำอธิบายจะถูกปิดเสียงเมื่อคุณยกเลิกการทำเครื่องหมายในช่อง - person Tony; 02.04.2019
comment
ขอบคุณโทนี่! มีวิธีลบบรรทัดแทนที่จะซ่อนไหม? - person jean; 02.04.2019
comment
ไม่รองรับการลบสัญลักษณ์อย่างเป็นทางการ ไม่ใช่เรื่องที่เป็นไปไม่ได้แต่ดูเหมือนจะยุ่งยากสำหรับฉันเพราะคุณสามารถเลอะเทอะได้ง่าย หากคุณต้องการลบหรือเพิ่มคำอธิบายแผนภูมิ คุณสามารถใช้ p3.legend[0].items.pop() และ p3.legend[0].items.append(LegendItem(label = 'label', renderers = [renderer]) ) แต่ฉันจะไม่ทำอย่างนั้น - person Tony; 02.04.2019
comment
คุณจะบันทึกการเล่นด้วยแดชบอร์ดโบเก้ดังที่แสดงในผลลัพธ์ด้านบนได้อย่างไร - person jean; 12.04.2019
comment
บน Mac ฉันใช้ Quick Time Player (ไฟล์ =› การบันทึกหน้าจอใหม่) เพื่อบันทึกวิดีโอสั้น จากนั้นฉันใช้ FFMPEG เพื่อแปลงเป็นภาพ GIF FFMPEG ไม่ได้รวมอยู่ใน Mac มาตรฐาน ดังนั้นคุณจะต้องติดตั้ง คำสั่ง FFMPEG คือ: ffmpeg -i input.mov -r 10 -pix_fmt rgb24 -f gif - | gifsicle --delay=8 > output.gif - person Tony; 23.04.2019