Choosing order of bars in Bokeh bar chart

2019-03-30 01:11发布

问题:

As part of trying to learn to use Bokeh I am trying to make a simple bar chart. I am passing the labels in a certain order (days of the week) and Bokeh seems to be sorting them alphabetically. How can I have the bars show up in the order of the original list?

from bokeh.plotting import show
from bokeh.io import output_notebook
from bokeh.charts import Bar
from collections import OrderedDict
import calendar 

output_notebook()

data = OrderedDict()
data['values'] = [2,3,4,5,6,7,8] #values only ascending to make correct graph clear
data['days'] = [calendar.day_name[i-1] for i in range(7)]
p = Bar(data, label='days', values='values', 
         title='OrderedDict Input',xlabel="Day", ylabel="Value")
show(p)

Output generated

回答1:

I am no big fan of high level charts such as Bar plots. They are not very customizable. Building them 'by hand' is often easier -and not necessary much longer. This is what I would do:

from bokeh.plotting import figure
from bokeh.io import output_file, show
import calendar

values = [2,3,4,5,6,7,8]
days = [calendar.day_name[i-1] for i in range(1,8)]

p = figure(x_range=days)
p.vbar(x=days, width=0.5, top=values, color = "#ff1200")

output_file('foo.html')
show(p)

which yields:



回答2:

Note from Bokeh project maintainers: This answer refers to an obsolete and deprecated API that should not be used in any new code. For information about creating bar charts with modern and fully supported Bokeh APIs, see other responses.


Here's how to retain original order of the labels in your example using the Charts interface, tested with Bokeh 0.11.1.

from bokeh.plotting import show
from bokeh.io import output_notebook
from bokeh.charts import Bar
from collections import OrderedDict
import calendar 
from bokeh.charts.attributes import CatAttr

output_notebook()

data = OrderedDict()
data['values'] = [2,3,4,5,6,7,8] #values only ascending to make correct graph clear
data['days'] = [calendar.day_name[i-1] for i in range(7)]
p = Bar(data, label=CatAttr(columns=['days'], sort=False), 
        values='values',title='OrderedDict Input',xlabel="Day", ylabel="Value")
show(p)


回答3:

In general, with any plot you should be able to specify the x (or y) range explicitly. tk's answer is helpful if you want to completely disregard the Bar chart class (which, for reasons mentioned, is not the worst idea in the world). user666's answer is helpful if your data columns are already ordered the way you want them. Otherwise you can specify the order yourself:

Week starts on Sunday:

from bokeh.models import FactorRange
...
p.x_range = FactorRange(factors=data['days'])

Week starts on Monday:

p.x_range = FactorRange(factors=data['days'][1:] + [data['days'][0]])



回答4:

This is a comment related to the answer from user666 (I don't have sufficient credits to add comments.)

I don't think the use of OrderedDict is helping here, as it remembers only the order that keys were inserted (i.e. 'values' comes before 'days'), and not the order of sequences that are the values associated with those keys.

Also FYI there is a discussion of this issue on the bokeh GitHub site here: https://github.com/bokeh/bokeh/issues/2924 and here: https://github.com/bokeh/bokeh/pull/3623