# Can't order legend entries in hbar plot

**URL:** <https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816>\
**Category:** Community Support\
**Created:** [July 28, 2019, 10:17pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816 "2019-07-28T22:17:20Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![arturomoncadatorres](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/arturomoncadatorres/32/1029_2.png) [@arturomoncadatorres](https://discourse.bokeh.org/u/arturomoncadatorres)\
**Post date:** [July 28, 2019, 10:17pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/1 "2019-07-28T22:17:20Z")

</div>

I understand that currently they are displayed as the glyphs are created. However, I would like to change that order, since it isn’t logical for the data. I’ve been trying to change the order without success. I found [one example](https://github.com/bdwiel/bokeh/blob/stacked_area_legend_example/examples/plotting/file/stacked_area.py), but not even this works. Apparently you can [fix this by hand](https://discourse.bokeh.org/t/legend-ordering/2224/3), but I haven’t found a way to 1. look into the items to see which corresponds to what and 2. actually change the order itself.

Currently using Python 3.7.3 and bokeh 1.2.0 in Jupyter notebook.

Any help would be appreciated. Thanks!

---

<div class="post-metadata">

**Author:** ![Bryan](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/bryan/32/3625_2.png) [@Bryan](https://discourse.bokeh.org/u/Bryan)\
**Post date:** [July 28, 2019, 11:23pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/2 "2019-07-28T23:23:41Z")

</div>

Every [`LegendItem`](https://bokeh.pydata.org/en/latest/docs/reference/models/annotations.html#bokeh.models.annotations.LegendItem) has a `label` property corresponding to the label you set in the glyph method call. So that is how you can see what is what. As for reordering, it is a Python list, so you can re-order it in any of the standard ways, e.g with `sorted` and key function. Once you have a new list of the legend items in the order you want:

```
plot.legend.items = items_in_new_order
```

---

<div class="post-metadata">

**Author:** ![arturomoncadatorres](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/arturomoncadatorres/32/1029_2.png) [@arturomoncadatorres](https://discourse.bokeh.org/u/arturomoncadatorres)\
**Post date:** [July 29, 2019, 10:00pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/4 "2019-07-29T22:00:02Z")

</div>

Thanks for the quick reply! I think I am starting to understand it. However, I still can’t get it working. Maybe a little bit of more background information might help:

I created a `ColumnDataSource` from a pandas data frame:

`source = ColumnDataSource(df[['name', 'count', 'type']])`

Then, I create the plot `p`:

```auto
p = figure(y_range=FactorRange(factors=name, bounds=(0, len(name))))
p.hbar(y='name', left=0, right='count', height=0.9, legend='type', source=source)

```

and add the legend

```auto
p.legend.title = 'Type'
p.legend.location = 'bottom_right'

```

When I look into the legend items, I don’t [get a list of legend items](https://discourse.bokeh.org/t/legend-ordering/2224/2). In its place, I get a list of length 1:

```auto
p.legend[0].items
[LegendItem(id='16472', ...)]

```

Furthermore, if I look at its label, I get

```auto
p.legend[0].items[0].label
{'field': 'type'}

```

What should I do different to actually get a list of LegendItems?

---

<div class="post-metadata">

**Author:** ![Bryan](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/bryan/32/3625_2.png) [@Bryan](https://discourse.bokeh.org/u/Bryan)\
**Post date:** [July 29, 2019, 10:54pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/5 "2019-07-29T22:54:08Z")

</div>

@arturomoncadatorres ah, I did not realize you were using a [“GroupBy Legend”](https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#automatic-grouping). The reason there is only one item is because the real items and their order is only computed on the JavaScript side, in the browser. I am afraid I don’t have a good suggestion for you at the moment, if you want to keep using that feature, as there are not currently any user-facing hooks or properties that would affect the default ordering that is produced now. A GitHub issue to discuss adding some user-control over the order would be appropriate.

Otherwise, you will need to construct all the legend items (one for each group) all manually, using [Explicit Indices](https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#explicit-index) into the data columns.

---

<div class="post-metadata">

**Author:** ![arturomoncadatorres](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/arturomoncadatorres/32/1029_2.png) [@arturomoncadatorres](https://discourse.bokeh.org/u/arturomoncadatorres)\
**Post date:** [August 1, 2019, 10:15pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/6 "2019-08-01T22:15:24Z")

</div>

Sorry for my late reply. I didn’t have time in the previous days to test this. A-ha! That works. For future reference, this is what I ended doing (pretty much what the Explicit Indices documentation indicates):

```auto
legend = Legend(items=[
    LegendItem(label='1', renderers=[r_overall], index=6),
    LegendItem(label='2', renderers=[r_overall], index=37),
    LegendItem(label='3', renderers=[r_overall], index=1),
    LegendItem(label='4', renderers=[r_overall], index=10),
    LegendItem(label='5', renderers=[r_overall], index=2),
    LegendItem(label='6', renderers=[r_overall], index=14),
    LegendItem(label='7', renderers=[r_overall], index=8),
], title='Type', location='bottom_right')
p_overall.add_layout(legend)

```

However, now I have the issue that the plot has two legends:

![Capture](https://discourse-uploads.bokeh.org/original/2X/f/f485a7b7001ba37e75d9ee092d82abb08e7a4752.png)

If I remove `p_overall.add_layout(legend)`, I just get the bottom legend:

![Capture2](https://discourse-uploads.bokeh.org/original/2X/3/321fd2b27f171ffbba6e2c906aba613f2dac0644.png)

Is this expected behaviour (and therefore maybe a bug?) or am I doing something wrong?

---

<div class="post-metadata">

**Author:** ![Bryan](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/bryan/32/3625_2.png) [@Bryan](https://discourse.bokeh.org/u/Bryan)\
**Post date:** [August 1, 2019, 10:46pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/7 "2019-08-01T22:46:53Z")

</div>

if you pass `legend=` to glyph methods, Bokeh will automatically add one legend. So then calling `p_overall.add_layout(legend)` will add another. So that seems expected. I if you are adding a legend manually then you probably _don’t_ want to pass `legend=` to glyph methods (lr alternatively, if you leave then, you might want to re-configure the automatically generated legend, rather than add a new one)

---

<div class="post-metadata">

**Author:** ![arturomoncadatorres](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/arturomoncadatorres/32/1029_2.png) [@arturomoncadatorres](https://discourse.bokeh.org/u/arturomoncadatorres)\
**Post date:** [August 1, 2019, 11:16pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/8 "2019-08-01T23:16:25Z")

</div>

Gotcha. In case someone comes across this post looking for a solution, the final chunk of code looks like this:

```auto
# Define source
source = ColumnDataSource(df[['name', 'count', 'type']])

# Create figure
p = figure(y_range=FactorRange(factors=name, bounds=(0, len(name))))
r = p.hbar(y='name', left=0, right='count', height=0.9, source=source)

# Add legend
legend = Legend(items=[
    LegendItem(label='1', renderers=[r], index=6),
    LegendItem(label='2', renderers=[r], index=37),
    LegendItem(label='3', renderers=[r], index=1),
    LegendItem(label='4', renderers=[r], index=10),
    LegendItem(label='5', renderers=[r], index=2),
    LegendItem(label='6', renderers=[r], index=14),
    LegendItem(label='7', renderers=[r], index=8),
], title='Type', location='bottom_right')
p.add_layout(legend)

```

where the indexes were obtained manually (can probably be done programatically).

---

<div class="post-metadata">

**Author:** ![arturomoncadatorres](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/arturomoncadatorres/32/1029_2.png) [@arturomoncadatorres](https://discourse.bokeh.org/u/arturomoncadatorres)\
**Post date:** [August 1, 2019, 11:19pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/9 "2019-08-01T23:19:38Z")

</div>

Would it be worth mentioning in the documentation about [how ordering the items of a GroupBy Legend doesn’t work as a “normal” legend](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/5)?

I will also create a Github issue to put it on the table 😉 . Thanks for your help!

---

<div class="post-metadata">

**Author:** ![Bryan](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/bryan/32/3625_2.png) [@Bryan](https://discourse.bokeh.org/u/Bryan)\
**Post date:** [August 1, 2019, 11:39pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/10 "2019-08-01T23:39:41Z")

</div>

GH issue definitely reasonable here, both for improving the docs, and possibly coming up with a python side helper function for situations like this.

---

<div class="post-metadata">

**Author:** ![system](https://discourse-uploads.bokeh.org/original/2X/1/14eb24f9e10e4e9b78e3f10f66c04ffa96446e5a.svg) [@system](https://discourse.bokeh.org/u/system)\
**Post date:** [July 21, 2021, 9:18pm UTC](https://discourse.bokeh.org/t/cant-order-legend-entries-in-hbar-plot/3816/11 "2021-07-21T21:18:15Z")

</div>


