Ross Cheeseright
Ross Cheeseright

Reputation: 57

How can I prevent my HBars from overlapping in Bokeh?

I have 'categorical data' groups of things that have run for a period of time. Some of these things also ran concurrently. I wanted to display these categories on a timeline in Bokeh Python.

However, the original attempt wasn't successful: enter image description here

After that, I tried to jitter them, but it created something quite messy and unstructured (probably the point of jitter and I'm just not using it correctly.) enter image description here

Ideally, I would just like a method that allows me to stagger these items within each category, but I am not sure how.

Any advice would be appreciated!

Upvotes: 1

Views: 660

Answers (1)

bigreddot
bigreddot

Reputation: 34618

You don't want to jitter, you want to visually dodge, which is demonstrated in the documentation.

from bokeh.io import show
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.transform import dodge

fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ['2015', '2016', '2017']

data = {'fruits' : fruits,
        '2015'   : [2, 1, 4, 3, 2, 4],
        '2016'   : [5, 3, 3, 2, 4, 6],
        '2017'   : [3, 2, 4, 4, 5, 3]}

source = ColumnDataSource(data=data)

p = figure(x_range=fruits, y_range=(0, 10), plot_height=250)
p.vbar(x=dodge('fruits', -0.25, range=p.x_range), top='2015', width=0.2, source=source, color="#c9d9d3")
p.vbar(x=dodge('fruits',  0.0,  range=p.x_range), top='2016', width=0.2, source=source, color="#718dbf")
p.vbar(x=dodge('fruits',  0.25, range=p.x_range), top='2017', width=0.2, source=source, color="#e84d60")

p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None

show(p)

enter image description here

Alteratively, you might use explicit Categorical Offsets:

fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']

offsets = [-0.5, -0.2, 0.0, 0.3, 0.1, 0.3]

# This results in [ ['Apples', -0.5], ['Pears', -0.2], ... ]
x = list(zip(fruits, offsets))

p.vbar(x=x, top=[5, 3, 4, 2, 4, 6], width=0.8)

enter image description here

Upvotes: 2

Related Questions