Figure is not updating when column data source is updated

Hello,

I am new to bokeh. I want to update the graph as select the option from the select.
Column data source is updated as i select the option but i am getting empty figure.

Below is the code.

button = Button(label="Foo")
l = ["yew","no"]

select = Select(title="Option:",options=l)#filt_source.data["lables"]

fruits= []

data = {'fruits' : fruits,
        '2015'   : [],
        '2016'   : [],
        '2017'   : []}

#source = ColumnDataSource(data=data)

p = figure(x_range=FactorRange(),plot_height=350, title="Fruit Counts by Year",
           toolbar_location=None, tools="")



def update_fig(data):
    
    source = ColumnDataSource(data=data)
    
    fruits= source.data["fruits"]
    
    p.x_range = FactorRange(factors=fruits)

    print(source.data["2015"])
    
    p.vbar(x=dodge('fruits', -0.25, range=p.x_range), top='2015', width=0.2, source=source,
           color="#c9d9d3", legend_label="2015")

    p.vbar(x=dodge('fruits',  0.0,  range=p.x_range), top='2016', width=0.2, source=source,
           color="#718dbf", legend_label="2016")

    p.vbar(x=dodge('fruits',  0.25, range=p.x_range), top='2017', width=0.2, source=source,
           color="#e84d60", legend_label="2017")


def refresh_button():
    select.options = ['A','B','C']


def get_data(name):
    
    if name == "A":
        fruits= ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
        
        data = {'fruits' : fruits,
        '2015'   : [2, 1, 4, 3, 2, 4],
        '2016'   : [5, 3, 3, 2, 4, 6],
        '2017'   : [3, 2, 4, 4, 5, 3]}
        
    elif name == "B":
        fruits= ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
        data = {'fruits' : fruits,
        '2015'   : [0, 1, 4, 3, 2, 4],
        '2016'   : [0, 3, 3, 2, 4, 6],
        '2017'   : [1, 2, 4, 4, 5, 3]}

    elif name == "C":
        fruits= ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
        data = {'fruits' : fruits,
        '2015'   : [0, 1, 4, 3, 2, 4],
        '2016'   : [0, 0, 3, 2, 4, 6],
        '2017'   : [1, 2, 4, 4, 5, 3]}

    else:
        print("No values")
    return data


def select_graph(attrname,old,new):
    print(new)
    data = get_data(new)
    source = data
    update_fig(source)
        
button.on_click(refresh_button)
select.on_change('value', select_graph)
lay_out = layout([button],[select],[p]) 
curdoc().add_root(lay_out)

Hi @Shubj please edit your post to use code formatting so that the code is intelligible (either with the </> icon on the editing toolbar, or triple backtick ``` fences around the code blocks)

1 Like

You may get an idea of what’s going on in this answer: https://stackoverflow.com/a/61301628/564509

@p-himik Thanks for the reply.

I am not able to get it. can you explain bit more on this or give me some reference to understand it.

Instead of creating new Bokeh models and calling vbar again and again, create and set everything up just once. Then, just update the ColumnDataSource.data property of the relevant data sources. Take a look at this simple example: https://docs.bokeh.org/en/latest/docs/user_guide/server.html#single-module-format

still not able to find out the reason why I am getting empty graph?
Even values related to select are printing perfeact on terminal but unable to create graph.

button = Button(label="Foo")
l = ["yes","no"]

select = Select(title="Option:",options=l)#filt_source.data["lables"]

fruits= []

data = {'fruits' : fruits,
        '2015'   : [],
        '2016'   : [],
        '2017'   : []}

source = ColumnDataSource(data=data)

p = figure(x_range=FactorRange(),plot_height=350, title="Fruit Counts by Year",
           toolbar_location=None, tools="")

r = p.vbar(x=dodge('fruits', -0.25, range=p.x_range), top='2015', width=0.2, source=source,
           color="#c9d9d3", legend_label="2015")

r1 = p.vbar(x=dodge('fruits',  0.0,  range=p.x_range), top='2016', width=0.2, source=source,
       color="#718dbf", legend_label="2016")

r3 = p.vbar(x=dodge('fruits',  0.25, range=p.x_range), top='2017', width=0.2, source=source,
       color="#e84d60", legend_label="2017")



def update_fig(data):
     new_scr =  ColumnDataSource(data=data)
     p.x_range = FactorRange(factors=new_scr.data["fruits"])
     r.data_source = new_scr
     r1.data_source = new_scr
     r3.data_source = new_scr
     

def refresh_button():
    select.options = ['A',"B","C"]


def get_data(name):
    
    if name == "A":
        fruits= ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
        
        data = {'fruits' : fruits,
        '2015'   : [2, 1, 4, 3, 2, 4],
        '2016'   : [5, 3, 3, 2, 4, 6],
        '2017'   : [3, 2, 4, 4, 5, 3]}
        
    elif name == "B":
        fruits= ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
        data = {'fruits' : fruits,
        '2015'   : [0, 1, 4, 3, 2, 4],
        '2016'   : [0, 3, 3, 2, 4, 6],
        '2017'   : [1, 2, 4, 4, 5, 3]}

    elif name == "C":
        fruits= ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
        data = {'fruits' : fruits,
        '2015'   : [0, 1, 4, 3, 2, 4],
        '2016'   : [0, 0, 3, 2, 4, 6],
        '2017'   : [1, 2, 4, 4, 5, 3]}

    else:
        print("No values")
    return data


def select_graph(attrname,old,new):
    print(new)
    data = get_data(new)
    source = data
    update_fig(source)


print(source.data["2015"])   
button.on_click(refresh_button)
select.on_change('value', select_graph)
lay_out = layout([button],[select],[p]) 
curdoc().add_root(lay_out)

I have check example given in bokeh .
how will the update the range of figure object ? if x_range is dynamic.

Your plot is empty because you don’t update the data property of the data source. This line source = data does not override the data source, it just creates a local variable within the function. Even if you did override the variable source, Bokeh couldn’t possibly know about this change because it would still have references to the old data source.

Let me reiterate - do not create new models when you change the data, unless you know very well what you’re doing. Just change the data within the existing models, that’s it.

1 Like

@p-himik Thank you so much for the help. :+1: :+1: :pray:
I am able to show the update figure object.
It will be really helpful if you could guide me to

how to update the range of figure object ? if x_range is dynamic

1 Like