Bokeh Position Legend outside plot area for stacked vbar

巧了我就是萌 提交于 2021-01-29 12:50:43

问题


I have a stacked vbar chart in Bokeh, a simplified version of which can be reproduced with:

from bokeh.plotting import figure
from bokeh.io import show

months = ['JAN', 'FEB', 'MAR']
categories = ["cat1", "cat2", "cat3"]
data = {"month" : months,
        "cat1"  : [1, 4, 12],
        "cat2"  : [2, 5, 3],
        "cat3"  : [5, 6, 1]}
colors = ["#c9d9d3", "#718dbf", "#e84d60"]

p = figure(x_range=months, plot_height=250, title="Categories by month",
           toolbar_location=None)
p.vbar_stack(categories, x='month', width=0.9, color=colors, source=data)

show(p)

I want to add a legend to the chart, but my real chart has a lot of categories in the stacks and therefore the legend would be very large, so I want it to be outside the plot area to the right.

There's a SO answer here which explains how to add a legend outside of the plot area, but in the example given each glyph rendered is assigned to a variable which is then labelled and added to a Legend object. I understand how to do that, but I believe the vbar_stack method creates mutliple glyphs in a single call, so I don't know how to label these and add them to a separate Legend object to place outside the chart area?

Alternatively, is there a simpler way to use the legend argument when calling vbar_stack and then locate the legend outside the chart area?

Any help much appreciated.


回答1:


For anyone interested, have now fixed this using simple indexing of the vbar_stack glyphs. Solution below:

from bokeh.plotting import figure
from bokeh.io import show
from bokeh.models import Legend

months = ['JAN', 'FEB', 'MAR']
categories = ["cat1", "cat2", "cat3"]
data = {"month" : months,
        "cat1"  : [1, 4, 12],
        "cat2"  : [2, 5, 3],
        "cat3"  : [5, 6, 1]}
colors = ["#c9d9d3", "#718dbf", "#e84d60"]

p = figure(x_range=months, plot_height=250, title="Categories by month",
           toolbar_location=None)
v = p.vbar_stack(categories, x='month', width=0.9, color=colors, source=data)

legend = Legend(items=[
    ("cat1",   [v[0]]),
    ("cat2",   [v[1]]),
    ("cat3",   [v[2]]),
], location=(0, -30))

p.add_layout(legend, 'right')

show(p)



回答2:


Thanks Toby Petty for your answer.

I have slightly improved your code so that it automatically graps the categories from the source data and assigns colors. I thought this might be handy as the categories are often not explicitly stored in a variable and have to be taken from the data.

from bokeh.plotting import figure
from bokeh.io import show
from bokeh.models import Legend
from bokeh.palettes import brewer

months = ['JAN', 'FEB', 'MAR']
data = {"month" : months,
        "cat1"  : [1, 4, 12],
        "cat2"  : [2, 5, 3],
        "cat3"  : [5, 6, 1],
        "cat4"  : [8, 2, 1],
        "cat5"  : [1, 1, 3]}
categories = list(data.keys())
categories.remove('month')
colors = brewer['YlGnBu'][len(categories)]

p = figure(x_range=months, plot_height=250, title="Categories by month",
           toolbar_location=None)
v = p.vbar_stack(categories, x='month', width=0.9, color=colors, source=data)

legend = Legend(items=[(x, [v[i]]) for i, x in enumerate(categories)], location=(0, -30))

p.add_layout(legend, 'right')

show(p)


来源:https://stackoverflow.com/questions/53215062/bokeh-position-legend-outside-plot-area-for-stacked-vbar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!