Reputation: 20113
Based on the first example of the user-guide of Bokeh,
from bokeh.io import show, output_file
from bokeh.plotting import figure
from bokeh.models import Span
output_file("bars.html")
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
counts = [5, 3, 4, 2, 4, 6]
p = figure(x_range=fruits, plot_height=250, title="Fruit Counts",
toolbar_location=None, tools="")
p.vbar(x=fruits, top=counts, width=0.9)
# these two lines
vline = Span(location='Apples', dimension='height', line_color='blue', line_width=4)
p.renderers.extend([vline])
p.xgrid.grid_line_color = None
p.y_range.start = 0
show(p)
I am trying to add a vertical line to a bar plot whose x-range are categories. However, this does not seem to be possible, as this raises an error "ValueError: expected a value of type Real, got Apples of type str".
location='Apples'
does not work as intended as it expected a number.
Upvotes: 0
Views: 2610
Reputation: 20113
One solution is to convert the categorical value to the corresponding numeric value on the plot:
index = p.x_range.factors.index("Apples")
delta = (p.x_range.end - p.x_range.start)/p.x_range.factors.length;
location = delta/2 + index;
If the plot is dynamic (e.g. values are not known when the plot is built), then use an auxiliary JS function to do the conversion:
function _value_to_location(x_range, value) {
var index = x_range.factors.findIndex(x => x == value)
var delta = (x_range.end - x_range.start)/x_range.factors.length;
return delta/2 + index;
};
...
vline.location = _value_to_location(figure.x_range, "Apples");
Upvotes: 2