Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
436 views
in Technique[技术] by (71.8m points)

python - Bokeh not updating plot line update from CheckboxGroup

I'm following this great tutorial to play a little bit with Bokeh.

Basically, I have a figure with two independent line added to it. Everything is rendered properly but when I want to update nothing happens even if I checked that the new ColumnDataSource is well updated with the new values.

I render it using the command : bokeh serve --show my_app

Here is how I create my 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

My incoming data is JSON and looks like this :

# {"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'])

Thank you for your insights

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This will not function correctly:

src_p6.data = new_src.data

The ColumnDataSource is one of the most complicated objects in Bokeh, e.g. the .data object on a CDS is not a plain Python dict, it has lots of special instrumentation to make things like efficient streaming possible. But it is also tied to the CDS it is created on. Ripping the .data out of one CDS and putting assigning it to another is not going to work. We probably need to find a way to make that complain, I am just not sure how, offhand.

In any case, you need to assign .data from a plain Python dict, as all the examples and demonstrations do:

src_p6.data = dict(...)

For your sepcific code, that probably means having make_dataset just return the dicts it creates directly, instead of putting them in dataframes then making a CDS out of that.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...