# Order of legend entries in AlgebraOfGraphics

**URL:** <https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753>\
**Category:** Visualization\
**Tags:** algebraofgraphics\
**Created:** [March 11, 2022, 2:45pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753 "2022-03-11T14:45:25Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jakob](https://avatars.discourse-cdn.com/v4/letter/j/71c47a/32.png) [@Jakob](https://discourse.julialang.org/u/Jakob)\
**Post date:** [March 11, 2022, 2:45pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/1 "2022-03-11T14:45:25Z")

</div>

Hi everyone,

does anyone know of a way to specify the order of the legend entries created by AlgebraOfGraphics?  
In the following, the labels get reordered alphabetically but i’d like them to stay in the original order:

```julia
d = (;y = rand(3), x = string.('a':'c'), c = ["x", "z", "y"])
p = data(d) * mapping(:x, :y, color=:c) * visual(BarPlot)
draw(p)

```

 ![grafik](https://global.discourse-cdn.com/julialang/original/3X/8/3/83268b621c658ba8d08079303af454bdb24fd024.png)

Thanks!

---

<div class="post-metadata">

**Author:** ![icweaver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/icweaver/32/45764_2.png) [@icweaver](https://discourse.julialang.org/u/icweaver)\
**Post date:** [March 12, 2022, 6:37pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/2 "2022-03-12T18:37:45Z")

</div>

I think you can just apply a [`sorter`](http://juliaplots.org/AlgebraOfGraphics.jl/dev/gallery/gallery/customization/legend/#Legend-tweaking) to your mapping:

```julia
using AlgebraOfGraphics, CairoMakie
set_aog_theme!()

labels = ["x", "z", "y"]
d = (x='a':'c', y=[1, 2, 3], c=labels)
p = data(d) * mapping(:x, :y, color=:c=>sorter(labels)) * visual(BarPlot)
draw(p)

```

 ![index](https://global.discourse-cdn.com/julialang/original/3X/4/0/403b21be1fb6c5f7462fe0d10234af4b447af509.png)

---

<div class="post-metadata">

**Author:** ![Jakob](https://avatars.discourse-cdn.com/v4/letter/j/71c47a/32.png) [@Jakob](https://discourse.julialang.org/u/Jakob)\
**Post date:** [March 14, 2022, 7:33am UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/3 "2022-03-14T07:33:18Z")

</div>

Thanks, yes sorter indeed works. But it also changes the color mapping, which doesn’t play well with color palettes:

```julia
labels = ["x", "z", "y"]
d = (x='a':'c', y=[1, 2, 3], c=labels)
pal = ["x" => "red", "y" => "blue", "z" => "green"]
p = data(d) * mapping(:x, :y, color=:c => sorter(d.c)) * visual(BarPlot)
draw(p, palettes = (;color=pal))

```

This throws the following error:

```julia
ArgumentError: Key AlgebraOfGraphics.Sorted{String}(0x00000001, "x") not found and no default values are present

    (::AlgebraOfGraphics.Cycler{String, String})(::AlgebraOfGraphics.Sorted{String})@scales.jl:20
    iterate@generator.jl:47[inlined]
    collect(::Base.Generator{Vector{AlgebraOfGraphics.Sorted{String}}, AlgebraOfGraphics.Cycler{String, String}})@array.jl:724
    apply_palette(::Vector{Pair{String, String}}, ::Vector{AlgebraOfGraphics.Sorted{String}})@scales.jl:28
    fitscale(::AlgebraOfGraphics.CategoricalScale{Vector{AlgebraOfGraphics.Sorted{String}}, Nothing, Vector{Pair{String, String}}})@scales.jl:57
    map!(::typeof(AlgebraOfGraphics.fitscale), ::Dictionaries.Dictionary{Union{Int64, Symbol}, Any}, ::Dictionaries.Dictionary{Union{Int64, Symbol}, Any})@map.jl:57
    var"#compute_axes_grid#116"(::NamedTuple{(), Tuple{}}, ::NamedTuple{(:color,), Tuple{Vector{Pair{String, String}}}}, ::typeof(AlgebraOfGraphics.compute_axes_grid), ::AlgebraOfGraphics.Layer)@layers.jl:143
    var"#compute_axes_grid#113"(::NamedTuple{(), Tuple{}}, ::NamedTuple{(:color,), Tuple{Vector{Pair{String, String}}}}, ::typeof(AlgebraOfGraphics.compute_axes_grid), ::Makie.Figure, ::AlgebraOfGraphics.Layer)@layers.jl:117
    #226@draw.jl:21[inlined]
    update@draw.jl:10[inlined]
    var"#plot!#225"(::NamedTuple{(), Tuple{}}, ::NamedTuple{(:color,), Tuple{Vector{Pair{String, String}}}}, ::typeof(MakieCore.plot!), ::Makie.Figure, ::AlgebraOfGraphics.Layer)@draw.jl:21
    (::AlgebraOfGraphics.var"#230#231"{NamedTuple{(), Tuple{}}, NamedTuple{(:color,), Tuple{Vector{Pair{String, String}}}}, NamedTuple{(), Tuple{}}, NamedTuple{(), Tuple{}}, NamedTuple{(), Tuple{}}, AlgebraOfGraphics.Layer})(::Makie.Figure)@draw.jl:46
    update@draw.jl:10[inlined]
    #draw#229@draw.jl:45[inlined]
    top-level scope@Local: 6[inlined]

```

---

<div class="post-metadata">

**Author:** ![icweaver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/icweaver/32/45764_2.png) [@icweaver](https://discourse.julialang.org/u/icweaver)\
**Post date:** [March 14, 2022, 3:22pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/4 "2022-03-14T15:22:53Z")

</div>

I don’t think I’ve seen a dictionary be used for a [palette](https://makie.juliaplots.org/stable/documentation/theming/index.html#palettes) before. Could you just pass your vector of colors directly?

```julia
draw(p, palettes=(; color=[:red, :green, :blue]))

```

 ![index](https://global.discourse-cdn.com/julialang/original/3X/e/f/ef40b03667243ad9848f38be122810bac6dd13dc.png)

---

<div class="post-metadata">

**Author:** ![Jakob](https://avatars.discourse-cdn.com/v4/letter/j/71c47a/32.png) [@Jakob](https://discourse.julialang.org/u/Jakob)\
**Post date:** [March 14, 2022, 3:40pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/5 "2022-03-14T15:40:26Z")

</div>

The pairs syntax for associating specific labels with a fixed color is from the [documentation (second example)](http://juliaplots.org/AlgebraOfGraphics.jl/dev/gallery/gallery/scales/custom_scales/#Custom-scales) and is really nice if you need to create many different plots with the same grouping but possibly varying subsets of labels. Maybe there’s a ‘hack’ to rearrange the legend labels after drawing.

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [March 14, 2022, 3:58pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/6 "2022-03-14T15:58:11Z")

</div>

That part is being reworked (see [this github comment](https://github.com/JuliaPlots/AlgebraOfGraphics.jl/issues/329#issuecomment-1052215915) and the discussion there in general).

There is a conceptual issue with the current approach where the keys of the dictionary in `pal` do not match the _transformed_ entries for your categorical variable (which are no longer just strings but strings + sorting information).

A “hack” around it would be to pass the transformed values to the palette, e.g.

```julia
labels = ["x", "z", "y"]
d = (x='a':'c', y=[1, 2, 3], c=labels)
transf = sorter(d.c)
pal = [transf("x") => "red", transf("y") => "blue", transf("z") => "green"]
p = data(d) * mapping(:x, :y, color=:c => transf) * visual(BarPlot)
draw(p, palettes = (; color=pal))

```

But the long term fix is probably to decouple the palette (which really should just be a list of color) and the “categorization of the variable” (convert from strings or other types to integres) in AlgebraOfGraphics.jl

EDIT: but yes, definitely do file an issue about this, it’s a valid use case to keep in mind when reworking the palette system

---

<div class="post-metadata">

**Author:** ![icweaver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/icweaver/32/45764_2.png) [@icweaver](https://discourse.julialang.org/u/icweaver)\
**Post date:** [March 14, 2022, 3:58pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/7 "2022-03-14T15:58:29Z")

</div>

> The pairs syntax for associating specific labels with a fixed color is from …

Oh that’s really handy, thanks for the example! It looks like things work until `sorter` is introduced:

```julia
colors = ["x" => "red", "y" => "blue", "z" => "green"]
p = data(d) * mapping(:x, :y; color=:c) * visual(BarPlot) # Work's
p = data(d) * mapping(:x, :y; color=:c=>sorter(d.c)) * visual(BarPlot) # Doesn't work
draw(p; palettes=(; color=colors))

```

This might be worth raising an issue?

---

<div class="post-metadata">

**Author:** ![icweaver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/icweaver/32/45764_2.png) [@icweaver](https://discourse.julialang.org/u/icweaver)\
**Post date:** [March 14, 2022, 3:58pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/8 "2022-03-14T15:58:57Z")

</div>

haha, @piever beat me to it

---

<div class="post-metadata">

**Author:** ![Jakob](https://avatars.discourse-cdn.com/v4/letter/j/71c47a/32.png) [@Jakob](https://discourse.julialang.org/u/Jakob)\
**Post date:** [March 14, 2022, 7:08pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/9 "2022-03-14T19:08:22Z")

</div>

I’ve filed an [issue](https://github.com/JuliaPlots/AlgebraOfGraphics.jl/issues/370). Thanks for the help!

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [March 17, 2022, 10:12am UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/10 "2022-03-17T10:12:03Z")

</div>

I was actually thinking about the following. Could it make sense to improve the `sorter` helper (maybe with a better name to subsume most of the various helpers we use) so that the pair syntax in the palette is not needed?

Essentially, one could use `:c => sorter("y", "x", "z")` to establish _levels_: `"y"` is `1`, `"x"` is `2` and `"z"` is `3`, regardless of what data is actually present. That way, passing the same palette will always yield consistent plots (regardless of data filtering), but now the palette is strictly a “theme component” (not data specific).

---

<div class="post-metadata">

**Author:** ![Jakob](https://avatars.discourse-cdn.com/v4/letter/j/71c47a/32.png) [@Jakob](https://discourse.julialang.org/u/Jakob)\
**Post date:** [March 17, 2022, 10:59am UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/11 "2022-03-17T10:59:25Z")

</div>

I like that. What would happen if I don’t pass all the names present in the data? If it would only include the specified names in the plot in the given order it would be similar to `select` for a `DataFrame`, wouldn’t it? Maybe it could be named accordingly.

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [March 18, 2022, 6:41pm UTC](https://discourse.julialang.org/t/order-of-legend-entries-in-algebraofgraphics/77753/12 "2022-03-18T18:41:43Z")

</div>

> [@Jakob](#):
>
> What would happen if I don’t pass all the names present in the data?

I was actually thinking that the other ones would just be attributed the following levels. This way, we’d keep supporting the “mixed approach”, ie only some entries get “fixed” attribute values.

For instance the old

```julia
# `a` and `b` entries get specified colors, for the other entries it's data-dependent
palette = (color=["a" => "red", "b" => "blue", "green", "black"],)

```

could be achieved with

```julia
mapping(color=v => sorter(["a", "b"])
palette = (color=["red", "blue", "green", "black"],)

```
