Dasbor interaktif bokeh tidak dapat menghapus garis dari plot

Saya sedang mengerjakan dasbor interaktif python Bokeh pertama saya. Default plot menunjukkan garis untuk grup=a dan grup=b. Jika kotak dicentang[1], plot akan menambahkan baris untuk grup=a1 dan grup=b1. Jika tidak dicentang [1], baris a1, b1 seharusnya dihapus dari plot, namun tetap berada di plot.

Di bawah ini adalah contoh data dan kode contoh saya. Itu bisa langsung dijalankan di notebook jupyter Anda. Adakah yang bisa membantu saya? Terima kasih banyak!

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 sumber


Jawaban (1)


Kemungkinan besar, masalahnya (yang sudah Anda perbaiki) ada pada garis bawah di baris ini:

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

Tentu saja yang seharusnya:

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

Jadi Anda mereferensikan a_1 di sumber (yang tidak ada) dan bukan a1.

Saya merasa bebas untuk meningkatkan kode Anda untuk juga menyembunyikan baris jika Anda membatalkan pilihan pada kotak centang. Kode ini untuk server Bokeh v1.0.4 tetapi juga dapat berfungsi untuk Jupyter Notebook setelah menghapus blok baris yang ditandai dan menghapus komentar pada baris yang dikomentari)

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)

Hasil:

masukkan deskripsi gambar di sini

person Tony    schedule 01.04.2019
comment
Terima kasih banyak! sekarang baris dapat ditambahkan/dihapus dari plot (persis seperti yang saya butuhkan), tetapi legenda selalu menampilkan 'a, b,a1,b1'. Bisakah Anda juga membuat legenda berubah sesuai dengan garis? Sangat menghargai itu !. - person jean; 01.04.2019
comment
Saya memindahkan p3.legend.click_policy = 'hide' ke tempat yang tepat dan sekarang legenda dibungkam ketika Anda menghapus centang pada kotak - person Tony; 02.04.2019
comment
Terima kasih, Tony! Apakah ada cara untuk menghilangkan garis tersebut, alih-alih menyembunyikannya? - person jean; 02.04.2019
comment
Menghapus mesin terbang tidak didukung secara resmi. Ini bukan tidak mungkin tetapi tampaknya sulit bagi saya karena Anda dapat mengacaukan segalanya dengan mudah. Jika Anda ingin menghapus atau menambahkan legenda maka Anda dapat menggunakan p3.legend[0].items.pop() dan p3.legend[0].items.append(LegendItem(label = 'label', renderers = [renderer]) ) tapi saya tidak akan melakukan itu. - person Tony; 02.04.2019
comment
bagaimana cara merekam permainan dengan dashboard bokeh seperti terlihat pada hasil di atas? - person jean; 12.04.2019
comment
Di Mac saya menggunakan Quick Time Player (File =› New Screen Recording) untuk merekam video pendek dan kemudian saya menggunakan FFMPEG untuk mengubahnya menjadi gambar GIF. FFMPEG bukan standar yang disertakan pada Mac sehingga Anda perlu menginstalnya. Perintah FFMPEG adalah: ffmpeg -i input.mov -r 10 -pix_fmt rgb24 -f gif - | gifsicle --delay=8 > output.gif - person Tony; 23.04.2019