我正在开发我的第一个python Bokeh交互式仪表板。绘图默认显示组= a和组= 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)
答案 0 :(得分: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)
结果: