散景不更新CheckboxGroup的情节线更新

时间:2018-07-23 15:40:19

标签: python plot bokeh

我正在追踪this great tutorial与Bokeh一起玩。

基本上,我有一个figure并添加了两个独立的line。一切都正确呈现,但是当我要更新时,即使我检查新的ColumnDataSource是否已使用新值很好地更新也没有任何反应。

我使用以下命令进行渲染:bokeh serve --show my_app

这是我创建figure的方式:

src_p6 = make_dataset(["select_a", "select_b"])
p6 = make_plot(src_p6)
select_selection = CheckboxGroup(labels=["select_a", "select_b"], active = [0, 1])
select_selection.on_change('active', update)
controls = WidgetBox(select_selection)
curdoc().add_root(column(controls, p6, width=1200))

def make_dataset(select_list):
  if 'select_a' in select_list and 'select_b' in select_list:
    tmp = pd.DataFrame({'time': df["time"], 
                       'a': df["a"], 
                       'b': df["b"]
                       })
  elif 'select_a' in select_list and 'select_b' not in select_list:
    tmp = pd.DataFrame({'time': df["time"], 
                       'a': df["a"]
                       })
  elif 'select_a' not in select_list and 'select_b' in select_list:
    tmp = pd.DataFrame({'time': df["time"], 
                       'b': df["b"]
                       })
  else:
    tmp = pd.DataFrame({'time': df["time"]
                       })

  src = ColumnDataSource(tmp)

  return src

def make_plot(plot_src):
  p = figure(plot_width=1000, plot_height=600, 
           title="Line x2 with hover and update",
           x_axis_label='Time', 
           y_axis_label='Values'
          )

  hover_content = [("Time", "@time")]

  if 'a' in plot_src.data:
    p.line(x='time', y='a', source=plot_src, legend="A", line_color="blue")
    hover_content.append(("A", "@a"))
  if 'b' in plot_src.data:
    p.line(x='time', y='b', source=plot_src, legend="B", line_color="red")
    hover_content.append(("B", "@b"))

  p.add_tools(HoverTool(tooltips=hover_content))

  return p

def update(attr, old, new):
  print(src_p6.data)

  select_to_plot = [select_selection.labels[i] for i in select_selection.active]

  new_src = make_dataset(select_to_plot)

  src_p6.data = new_src.data

  print("**********************")
  print(src_p6.data) # I see here that the data are well updated compared to the first print

我的传入数据是JSON,看起来像这样:

# {"data":[{"time":0,"a":123,"b":123},{"time":1,"a":456,"b":456},{"time":2,"a":789,"b":789}]}
# data = json.load(data_file, encoding='utf-8')
# df = pd.io.json.json_normalize(data['data'])

感谢您的见解

2 个答案:

答案 0 :(得分:2)

这将无法正常运行:

src_p6.data = new_src.data

ColumnDataSource是Bokeh中最复杂的对象之一,例如CDS上的.data对象不是Python的简单命令,它具有许多特殊的工具,可实现高效流式传输。但是,它也与创建它的CDS有联系。从一个CDS中剥离.data并将其分配给另一个CDS是行不通的。我们可能需要找到一种方法来投诉,但我不确定如何。

在任何情况下,您都需要从一个简单的Python字典中分配.data,就像所有示例和演示一样:

src_p6.data = dict(...)

对于您的特定代码,这可能意味着让make_dataset仅直接返回它直接创建的指令,而不是将它们放入数据帧中,然后从中制成CDS。

答案 1 :(得分:0)

首先感谢@bigreddot的时间和指导。

我最大的问题之一是我实际上并不想更新值,而只是显示/隐藏它,因此仅从源中删除它是行不通的

line函数中用make_plot语句添加if也不起作用,因为它仅在第一次创建绘图时才被调用。对于更新,它会更新图中的值,但不会从头开始重构所有内容... 因此,如果仅从一行开始,即使有可能,我也不知道它将如何创建新行。 ..


我开始简化make_dataset函数,使其仅返回一个简单的Python字典:

tmp = dict(time=df["time"], a=df["a"], b=df["b"])

但是当我想删除一行时,即使有更好的解决方案(我只是在这里与Bokeh一起玩),我还是使用了一个空数组:Line ON/OFFInteractive legend

empty = np.empty(len(df["time"])); empty.fill(None)
tmp = dict(time=df["time"], a=df["a"], b=empty)

当我第一次创建我的情节时,我会做:

src_p6 = ColumnDataSource(data=make_dataset(["select_a", "select_b"]))
p6 = make_plot(src_p6)

并且更新功能使用基本的python字典更新.data的{​​{1}}:

ColumnDataSource