0

I'm trying to upadte a vbar_stack plot in bokeh everytime I chosse a different category from a dropdown, but as legend_label is inside the vbar_plot, I can't update it in the update function.

I'll add the code to be more clear

def make_stacked_bar():

    colors = ["#A3E4D7", "#1ABC9C", "#117A65", "#5D6D7E", "#2E86C1", "#1E8449", "#A3E4D7", "#1ABC9C", "#117A65",
              "#5D6D7E", "#2E86C1", "#1E8449"]
    industries_ = sorted(np.unique(stb_src.data['industries']))
    p = figure(x_range=industries_, plot_height=800, plot_width=1200, title="Impact range weight by industry")

    targets = list(set(list(stb_src.data.keys())) - set(['industries', 'index']))

    p.vbar_stack(targets, x='industries', width=0.9, legend_label=targets, color=colors[:len(targets)], source=stb_src)

Here is the update function:

def update(attr, old, new):

    stb_src.data.update(make_dataset_stack().data)
    stb.x_range.factors = sorted(np.unique(stb_src.data['industries']))

How can I update the actual data and not only the x axis? Thanks!

Jose Ruiz
  • 77
  • 2
  • 13

1 Answers1

1

This would take some non-trivial work to make happen. The vbar_stack method is a convenience function that actually creates multiple glyph renderers, one for each "row" in the initial stacking. What's more the renderers are all inter-related to one another, via the Stack transform that stacks all the previous renderers at each step. So there is not really any simple way to change the number of rows that are stacked after the fact. So much so that I would suggest simply deleting and re-creating the entire plot in each callback. (I would not normally recommend this approach, but this situation is one of the few exceptions.)

Here is a complete example that updates an entire plot based on select widget:

from bokeh.layouts import column
from bokeh.models import Select
from bokeh.plotting import curdoc, figure

select = Select(options=["1", "2", "3", "4"], value="1")

def make_plot():
    p = figure()
    p.circle(x=[0,2], y=[0, 5], size=15)
    p.circle(x=1, y=float(select.value), color="red", size=15)
    return p

layout = column(select, make_plot())

def update(attr, old, new):
    p = make_plot()    # make a new plot
    layout.children[1] = p  # replace the old plot

select.on_change('value', update)

curdoc().add_root(layout)
bigreddot
  • 33,642
  • 5
  • 69
  • 122