Unable to update in bokeh serve a Categorical vbar chart, likely problem with x_range

Hi!

I’m new to Bokeh (started looking into it after Bryan session at PyData LA) and I’m pretty sure the fault is on my side but I’m unable to figure out what I’m doing wrong.

I’m trying to build a dashboard with a vbar figure (among others) where the data gets updated based on a Select widget.

Since I need to change x_range dynamically when building the figure I use x_range=FactorRange() and x_scale=CategoricalScale(), the FactorRange gets then modified in the update() callback.

The first chart works fine (the one built using the default value)

Screen Shot 2018-12-22 at 7.46.27 AM.png

but upon changing value in the Select all I get is a bit of clutter text on the top (that I can’t even read),

Screen Shot 2018-12-22 at 7.47.33 AM.png

What am I doing wrong? I’ve been trying to figure it out on my own for a while now (reading ML, docs, source code) but I’ve been unsuccessful.

Code is below

from bokeh.plotting import figure

from bokeh.layouts import layout

from bokeh.models import ColumnDataSource

from bokeh.models.widgets import Select

from bokeh.io import curdoc

from bokeh.models import FactorRange, CategoricalScale

data_selector = Select(title=“Snack or Breakfast”,

                   options=["Snack", "Breakfast"], 

                   value="Snack")

data = { ‘Snack’: { ‘food’: [“Apple”, “Orange”, “Banana”],

                'size': [1, 3, 2] 

              },

      'Breakfast': { 'food': ["Eggs", "Bacon"],

                     'size': [3, 7]

                   }

   }

source = ColumnDataSource(data=data[‘Snack’])

p = figure(plot_height=600,

       plot_width=700, 

       title="", 

       toolbar_location=None,

       x_range=FactorRange(),

       x_scale=CategoricalScale())

p.vbar(x=“food”, top=“size”, source=source, width=0.9)

def update():

p.title.text = data_selector.value

p.x_range = FactorRange(factors=data[data_selector.value]['food'])

source.data = data[data_selector.value]

data_selector.on_change(‘value’, lambda attr, old, new: update())

l = layout([[data_selector, p]])

update()

curdoc().add_root(l)

Just “bokeh serve thenameyousavedthecode.py”

Cheers,

Mauro

PS This is my first email to the ML, I apologize in advance if I’ll break any rule in this message (and if that happens please let me know so I can do better next time).

Hi,

Best practice in Bokeh is always to make the smallest change possible, and in particular, to change attributes of existing objects, rather than replacing those objects. So instead of replacing the entire FactorRange as you do, it is advised to update the exiting FactorRange, e.g.

  p.x_range.factors = data[data_selector.value]['food']

Thanks,

Bryan

···

On Dec 22, 2018, at 07:51, [email protected] wrote:

Hi!

I'm new to Bokeh (started looking into it after Bryan session at PyData LA) and I'm pretty sure the fault is on my side but I'm unable to figure out what I'm doing wrong.
I'm trying to build a dashboard with a vbar figure (among others) where the data gets updated based on a Select widget.
Since I need to change x_range dynamically when building the figure I use x_range=FactorRange() and x_scale=CategoricalScale(), the FactorRange gets then modified in the update() callback.

The first chart works fine (the one built using the default value)

<Screen Shot 2018-12-22 at 7.46.27 AM.png>

but upon changing value in the Select all I get is a bit of clutter text on the top (that I can't even read),

<Screen Shot 2018-12-22 at 7.47.33 AM.png>

What am I doing wrong? I've been trying to figure it out on my own for a while now (reading ML, docs, source code) but I've been unsuccessful.

Code is below

from bokeh.plotting import figure
from bokeh.layouts import layout
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Select
from bokeh.io import curdoc
from bokeh.models import FactorRange, CategoricalScale

data_selector = Select(title="Snack or Breakfast",
                       options=["Snack", "Breakfast"],
                       value="Snack")

data = { 'Snack': { 'food': ["Apple", "Orange", "Banana"],
                    'size': [1, 3, 2]
                  },
          'Breakfast': { 'food': ["Eggs", "Bacon"],
                         'size': [3, 7]
                       }
       }

source = ColumnDataSource(data=data['Snack'])

p = figure(plot_height=600,
           plot_width=700,
           title="",
           toolbar_location=None,
           x_range=FactorRange(),
           x_scale=CategoricalScale())
p.vbar(x="food", top="size", source=source, width=0.9)

def update():
    p.title.text = data_selector.value
    p.x_range = FactorRange(factors=data[data_selector.value]['food'])
    source.data = data[data_selector.value]

data_selector.on_change('value', lambda attr, old, new: update())

l = layout([[data_selector, p]])
update()
curdoc().add_root(l)

Just "bokeh serve thenameyousavedthecode.py"

Cheers,
Mauro

PS This is my first email to the ML, I apologize in advance if I'll break any rule in this message (and if that happens please let me know so I can do better next time).

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/48b5dbad-078e-4751-b442-b65c57d2b96f%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.
<Screen Shot 2018-12-22 at 7.46.27 AM.png><Screen Shot 2018-12-22 at 7.47.33 AM.png>

Thanks Bryan, it worked perfectly.
For my knowledge, was it me missing this best practice from the doc or is it not documented? I’m not complaining, just trying to figure out if I should have known better before wasting your time

···

On Monday, December 24, 2018 at 10:11:30 AM UTC-8, Bryan Van de ven wrote:

Hi,

Best practice in Bokeh is always to make the smallest change possible, and in particular, to change attributes of existing objects, rather than replacing those objects. So instead of replacing the entire FactorRange as you do, it is advised to update the exiting FactorRange, e.g.

    p.x_range.factors = data[data_selector.value]['food']

Thanks,

Bryan

On Dec 22, 2018, at 07:51, [email protected] wrote:

Hi!

I’m new to Bokeh (started looking into it after Bryan session at PyData LA) and I’m pretty sure the fault is on my side but I’m unable to figure out what I’m doing wrong.

I’m trying to build a dashboard with a vbar figure (among others) where the data gets updated based on a Select widget.

Since I need to change x_range dynamically when building the figure I use x_range=FactorRange() and x_scale=CategoricalScale(), the FactorRange gets then modified in the update() callback.

The first chart works fine (the one built using the default value)

<Screen Shot 2018-12-22 at 7.46.27 AM.png>

but upon changing value in the Select all I get is a bit of clutter text on the top (that I can’t even read),

<Screen Shot 2018-12-22 at 7.47.33 AM.png>

What am I doing wrong? I’ve been trying to figure it out on my own for a while now (reading ML, docs, source code) but I’ve been unsuccessful.

Code is below

from bokeh.plotting import figure

from bokeh.layouts import layout

from bokeh.models import ColumnDataSource

from bokeh.models.widgets import Select

from bokeh.io import curdoc

from bokeh.models import FactorRange, CategoricalScale

data_selector = Select(title=“Snack or Breakfast”,
options=[“Snack”, “Breakfast”],
value=“Snack”)

data = { ‘Snack’: { ‘food’: [“Apple”, “Orange”, “Banana”],

                'size': [1, 3, 2]
              },
      'Breakfast': { 'food': ["Eggs", "Bacon"],
                     'size': [3, 7]
                   }
   }

source = ColumnDataSource(data=data[‘Snack’])

p = figure(plot_height=600,
plot_width=700,
title="",
toolbar_location=None,

       x_range=FactorRange(),
       x_scale=CategoricalScale())

p.vbar(x=“food”, top=“size”, source=source, width=0.9)

def update():

p.title.text = data_selector.value
p.x_range = FactorRange(factors=data[data_selector.value]['food'])
source.data = data[data_selector.value]

data_selector.on_change(‘value’, lambda attr, old, new: update())

l = layout([[data_selector, p]])

update()

curdoc().add_root(l)

Just “bokeh serve thenameyousavedthecode.py”

Cheers,

Mauro

PS This is my first email to the ML, I apologize in advance if I’ll break any rule in this message (and if that happens please let me know so I can do better next time).


You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/48b5dbad-078e-4751-b442-b65c57d2b96f%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

<Screen Shot 2018-12-22 at 7.46.27 AM.png><Screen Shot 2018-12-22 at 7.47.33 AM.png>

Hi,

Questions here are not a waste of time, they are helpful to anyone that comes in the future. I would say this best practice has only been documented implicitly so far, i.e. all the examples and demos follow this advice. But it has come up several times recently, so it's probably worth stating explicitly somewhere in the docs.

Thanks,

Bryan

···

On Dec 24, 2018, at 12:30, [email protected] wrote:

Thanks Bryan, it worked perfectly.
For my knowledge, was it me missing this best practice from the doc or is it not documented? I'm not complaining, just trying to figure out if I should have known better before wasting your time

On Monday, December 24, 2018 at 10:11:30 AM UTC-8, Bryan Van de ven wrote:
Hi,

Best practice in Bokeh is always to make the smallest change possible, and in particular, to change attributes of existing objects, rather than replacing those objects. So instead of replacing the entire FactorRange as you do, it is advised to update the exiting FactorRange, e.g.

        p.x_range.factors = data[data_selector.value]['food']

Thanks,

Bryan

> On Dec 22, 2018, at 07:51, [email protected] wrote:
>
> Hi!
>
> I'm new to Bokeh (started looking into it after Bryan session at PyData LA) and I'm pretty sure the fault is on my side but I'm unable to figure out what I'm doing wrong.
> I'm trying to build a dashboard with a vbar figure (among others) where the data gets updated based on a Select widget.
> Since I need to change x_range dynamically when building the figure I use x_range=FactorRange() and x_scale=CategoricalScale(), the FactorRange gets then modified in the update() callback.
>
> The first chart works fine (the one built using the default value)
>
> <Screen Shot 2018-12-22 at 7.46.27 AM.png>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> but upon changing value in the Select all I get is a bit of clutter text on the top (that I can't even read),
>
> <Screen Shot 2018-12-22 at 7.47.33 AM.png>
>
> What am I doing wrong? I've been trying to figure it out on my own for a while now (reading ML, docs, source code) but I've been unsuccessful.
>
> Code is below
>
> from bokeh.plotting import figure
> from bokeh.layouts import layout
> from bokeh.models import ColumnDataSource
> from bokeh.models.widgets import Select
> from bokeh.io import curdoc
> from bokeh.models import FactorRange, CategoricalScale
>
> data_selector = Select(title="Snack or Breakfast",
> options=["Snack", "Breakfast"],
> value="Snack")
>
> data = { 'Snack': { 'food': ["Apple", "Orange", "Banana"],
> 'size': [1, 3, 2]
> },
> 'Breakfast': { 'food': ["Eggs", "Bacon"],
> 'size': [3, 7]
> }
> }
>
> source = ColumnDataSource(data=data['Snack'])
>
> p = figure(plot_height=600,
> plot_width=700,
> title="",
> toolbar_location=None,
> x_range=FactorRange(),
> x_scale=CategoricalScale())
> p.vbar(x="food", top="size", source=source, width=0.9)
>
> def update():
> p.title.text = data_selector.value
> p.x_range = FactorRange(factors=data[data_selector.value]['food'])
> source.data = data[data_selector.value]
>
> data_selector.on_change('value', lambda attr, old, new: update())
>
> l = layout([[data_selector, p]])
> update()
> curdoc().add_root(l)
>
>
> Just "bokeh serve thenameyousavedthecode.py"
>
> Cheers,
> Mauro
>
> PS This is my first email to the ML, I apologize in advance if I'll break any rule in this message (and if that happens please let me know so I can do better next time).
>
>
> --
> You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
> To post to this group, send email to [email protected].
> To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/48b5dbad-078e-4751-b442-b65c57d2b96f%40continuum.io.
> For more options, visit https://groups.google.com/a/continuum.io/d/optout.
> <Screen Shot 2018-12-22 at 7.46.27 AM.png><Screen Shot 2018-12-22 at 7.47.33 AM.png>

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/c0ef4997-41d3-400d-9ef6-63eb6a6f24dc%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.