# Odd behaviour of custom labels in Plot recipes

**URL:** <https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057>\
**Category:** General Usage\
**Tags:** plotting, plots, recipe\
**Created:** [February 9, 2022, 1:56am UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057 "2022-02-09T01:56:07Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![GoodDayToYouAll](https://avatars.discourse-cdn.com/v4/letter/g/ecd19e/32.png) [@GoodDayToYouAll](https://discourse.julialang.org/u/GoodDayToYouAll)\
**Post date:** [February 9, 2022, 1:56am UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/1 "2022-02-09T01:56:07Z")

</div>

Hello everyone,

I am very new to this forum as this is my first question here. I try to follow the guidelines for posting questions, but please point out any mistakes I do in this regard.

To my question: I want to plot a custom type which has fields `times` (a vector of numbers) and `data`, which is a `Vector` whose elements are either vectors or vectors of vectors. My goal is to have `times` on the x-axis, have a plotline with a custom label for each (nested) element in `data`. However, doing this by using `@recipe` and `@series` somehow mixes up the order of my labels (and I really don’t understand why).  
Here is the code of my minimal working example:

```julia
using Plots

struct MyData
    times
    data
end

@recipe function f(mydata::MyData)
    for (i,d) in enumerate(mydata.data)
        @series begin
            i==1 && (label --> "Constant")
            i==2 && (label --> ["Straight" "Small Random" "Big Random"])
            mydata.times, d
        end
    end
end
times = 1:10
vec = fill(2, 10)
vecofvec = [1:10, rand(10), 10*rand(10)]
mydata = MyData(times, [vec, vecofvec])
plot(mydata)

```

Which results in this plot

 ![image](https://global.discourse-cdn.com/julialang/original/3X/d/4/d4c002238f92c969c237ad8d05f1bd8de24e36e7.jpeg)

As you can see the order of the labels is mixed up compared to what I want. The first label is still correctly labelling the constant vector `vec`, but the labels for `vecofvec` are set off by one.

I figured out that changing `vec` to a vector of vectors of length two leads to a ‘label offset’ of two and that changing `-->` to `:=` does not help. However, putting the labels in the function call like

```julia
plot(mydata, label=["Constant" "Straight" "Small Random" "Big Random"])

```

works (but this is not what I want in the end!).

I would be very grateful if someone could explain to me why this happens and how I can circumvent it.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [February 9, 2022, 7:43am UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/2 "2022-02-09T07:43:35Z")

</div>

Hello, please check the code below which seems to work fine.

```julia
using Plots

struct MyData
    times
    data
end

@recipe function f(mydata::MyData)
    labels = ["Constant" "Straight" "Small Random" "Big Random"]
    label --> labels
    mydata.times, mydata.data
end

times = 1:10
vc = fill(2, 10)
vecofvec = [1:10, rand(10), 10*rand(10)]
mydata = MyData(times, [vc, vecofvec])
plot(mydata)

```

---

<div class="post-metadata">

**Author:** ![GoodDayToYouAll](https://avatars.discourse-cdn.com/v4/letter/g/ecd19e/32.png) [@GoodDayToYouAll](https://discourse.julialang.org/u/GoodDayToYouAll)\
**Post date:** [February 9, 2022, 11:00am UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/3 "2022-02-09T11:00:13Z")

</div>

Thank you for the very quick answer; your code indeed does work. However, my actual use case is more complicated as the labels are created by external functions and data transformations performed. Additionally I would like to flexibly change the series type of single data entries.  
So I think I would have more flexibility with the `@series` construction.

Also for more complicated recipes I would like to understand _why_ my example doesn’t work as expected.

Can you help me with that?

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [February 9, 2022, 12:05pm UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/4 "2022-02-09T12:05:56Z")

</div>

I don’t know why, but it seems that the labels are issued in reverse order compared to the series.

Just changing this line in your recipe to iterate in reverse, seems to fix it:

```julia
for (i,d) in Iterators.reverse(pairs(mydata.data))
...

```

---

<div class="post-metadata">

**Author:** ![GoodDayToYouAll](https://avatars.discourse-cdn.com/v4/letter/g/ecd19e/32.png) [@GoodDayToYouAll](https://discourse.julialang.org/u/GoodDayToYouAll)\
**Post date:** [February 9, 2022, 12:24pm UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/5 "2022-02-09T12:24:05Z")

</div>

Hmm … this seems to work in this case, because the labels of `vecofvec` offset the labels of `vc` by three, but that doesn’t matter since the length of the labels for `vc` is one. So nothing is changed.

In a little more complex example like below the ‘offset’ appears again

```julia
@recipe function f(mydata::MyData)
    for (i,d) in Iterators.reverse(pairs(mydata.data))
        @series begin
            i==1 && (label --> ["Constant = 2" "Big Random"])
            i==2 && (label --> ["Straight" "Small Random" "Constant = 10"])
            mydata.times, d
        end
    end
end
times = 1:10
vecofvec1 = [fill(2, 10), 10*rand(10)]
vecofvec2 = [1:10, rand(10), fill(10, 10)]
mydata = MyData(1:10, [vecofvec1, vecofvec2])

```

Note that it works if one changes `vecofvec2` to a vector of only two vectors, since the ‘offset’ due to the `vecofvec` labels would ‘iterate’ the labels of `vecofvec2` to its beginning again.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [February 9, 2022, 1:03pm UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/6 "2022-02-09T13:03:49Z")

</div>

I think you should preprocess the labels first and then call the @series macro. Try this:

```julia
@recipe function f(mydata::MyData)
    labels = String[]
    for (i,d) in pairs(mydata.data)
        i==1 && push!(labels, "Constant = 2", "Big Random")
        i==2 && push!(labels, "Straight", "Small, Random", "Constant = 10")
    end
    @series begin
        label --> permutedims(labels)
        mydata.times, mydata.data
    end
end

```

---

<div class="post-metadata">

**Author:** ![GoodDayToYouAll](https://avatars.discourse-cdn.com/v4/letter/g/ecd19e/32.png) [@GoodDayToYouAll](https://discourse.julialang.org/u/GoodDayToYouAll)\
**Post date:** [February 9, 2022, 2:20pm UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/7 "2022-02-09T14:20:43Z")

</div>

Yes, thank you , this works well. Event though I still believe there should be a nicer way to do this. Especially since (what I just figured out) this behaviour does not only affect labels but all `plotattributes` that I want to set in `@series` (so for example `linewidth`). Of course I can preprocess all of them in the way you showed, but there seems to be something I conceptually don’t understand about this macro.

But this is a nice workaround, so thanks!

---

<div class="post-metadata">

**Author:** ![BeastyBlacksmith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/beastyblacksmith/32/4741_2.png) [@BeastyBlacksmith](https://discourse.julialang.org/u/BeastyBlacksmith)\
**Post date:** [February 9, 2022, 3:30pm UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/8 "2022-02-09T15:30:25Z")

</div>

Just to explain why this happens:  
Plots sees 4 series and a 3 element label vector and thus cycles the vector to match the 4 series, so you get `["Straight" "Small Random" "Big Random" "Straight"]` and then it takes the values `2:4` from that vector and that gives you the order you are seeing.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [February 9, 2022, 3:49pm UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/9 "2022-02-09T15:49:53Z")

</div>

In any case, it seems that simplifying the data structure input to the `@series` macro is helpful here.  
Say converting `Vector{Vector{AbstractVector}}` to `Vector{AbstractVector}`

---

<div class="post-metadata">

**Author:** ![BeastyBlacksmith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/beastyblacksmith/32/4741_2.png) [@BeastyBlacksmith](https://discourse.julialang.org/u/BeastyBlacksmith)\
**Post date:** [February 9, 2022, 4:23pm UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/10 "2022-02-09T16:23:25Z")

</div>

I’d probably write this as

```julia
using Plots

struct MyData
    times
    data
end

@recipe function f(mydata::MyData)
    @series begin
        label := "Constant"
        mydata.times, first(mydata.data)
    end
    for (d, l) in zip(mydata.data[2],["Straight" "Small Random" "Big Random"])
        @series begin
            label := l
            mydata.times, d
        end
    end
end
times = 1:10
vec = fill(2, 10)
vecofvec = [1:10, rand(10), 10*rand(10)]
mydata = MyData(times, [vec, vecofvec])
plot(mydata)

```

---

<div class="post-metadata">

**Author:** ![GoodDayToYouAll](https://avatars.discourse-cdn.com/v4/letter/g/ecd19e/32.png) [@GoodDayToYouAll](https://discourse.julialang.org/u/GoodDayToYouAll)\
**Post date:** [February 10, 2022, 11:38am UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/11 "2022-02-10T11:38:44Z")

</div>

Thanks for the answer, but I still don’t quite understand. I thought the `@series` macro works by making a kind of local copy of the `plotattributes` and alters them individually for each series. Then it takes the seriesdata provided and basically appends the resulting series to the plot (kind of like `plots!`).  
So I believed that for `i==2` I more or less write

```julia
plot!(times, vecofvec, label = ["Straight" "Small Random" "Big Random"]

```

Apparently that’s not the case.  
So when you say that plots sees 4 series I guess you mean the one series from `vec` and three from `vecofvec` but why does it then not see a 4 element label vector `["Constant" "Straight" "Small Random" "Big Random"]`? I guess that has something to do with the fact that I change the labels during each series?

---

<div class="post-metadata">

**Author:** ![BeastyBlacksmith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/beastyblacksmith/32/4741_2.png) [@BeastyBlacksmith](https://discourse.julialang.org/u/BeastyBlacksmith)\
**Post date:** [February 10, 2022, 1:44pm UTC](https://discourse.julialang.org/t/odd-behaviour-of-custom-labels-in-plot-recipes/76057/12 "2022-02-10T13:44:05Z")

</div>

I think your expectation is reasonable. Its just that you can do stuff in recipes, that you can’t through the `plot/plot!` interface like in this example (you’d need two calls).  
So this wasn’t considered up to this point and it might be fixable, but until that you’d need to take one of the other routes.
