Plots - reset color cycle

Hi there. I have a plot with two different series (a scatterline and a fillrange). I want the fillrange (representing error) to be of the same color as the line.

Here is my code:

using DataFrames, Plots, Random
Random.seed!(12345)

test_data = DataFrame(
                [1:100, rand(100), sample(['A', 'B',], 100)],
                [:Image_no, :val1, :category]
            )
test_data.val_lo = test_data.val1 .- 0.1
test_data.val_hi = test_data.val1 .+ 0.1;

first(test_data, 5)
5 rows × 5 columns

Image_no	val1	category	val_lo	val_hi
Int64	Float64	Char	Float64	Float64
1	1	0.791805	B	0.691805	0.891805
2	2	0.159579	A	0.059579	0.259579
3	3	0.334191	B	0.234191	0.434191
4	4	0.811392	B	0.711392	0.911392
5	5	0.796629	A	0.696629	0.896629
plot(
    test_data.Image_no, test_data.val1, group=test_data.category,
    marker=:o, lw=1.5,
)
plot!(
    test_data.Image_no, test_data.val_lo,  group=test_data.category,
    fillrange=test_data.val_hi,
    alpha=0.5, 
)

Plots.jl uses the next colors of the color cycle of the palette for the fillranges, so that the colors do not match with those of the scatterline.

I have tried using different colors for the color or seriescolor arguments. For example I tried [1, 2] to select the first two colors of the palette, or i tried

using ColorSchemes

colors = ColorSchemes.tab10[1:2]

plot(..., color_palette=colors)

But none of this leads to my desired output (fillrange and line of the same color, but cycling through colors for each category).

If you add argument: color=[:red :blue], to both plot commands, the desired result will be obtained. Maybe you can generalize this idea.

You might be able to make use of the ribbon keyword:

plot(
    test_data.Image_no, test_data.val1, group=test_data.category,
    marker=:o, lw=1.5,
    ribbon=(test_data.val1-test_data.val_lo, test_data.val1+test_data.val_hi),
)
1 Like

@baggepinnen, just a minor typo on the second difference:
ribbon=(test_data.val1 - test_data.val_lo, test_data.val_hi - test_data.val1)

1 Like

Thanks for the help.

@rafael.guerra : If I use color=[:red, :blue], plots will alternate between red and blue for each datapoint of the individual series, leading to red(blue stripes in both series. If I use palette=[:red, :blue], I get my desired output (I guess because this changes the palette not the individual series color). This works with named colors as well as with ColorSchemes.jl, e.g., ..., palette=ColorSchemes.tab10[1:2]

@baggepinnen : Yes, I think the ribbon keyword works nicely in this case, because it reduces everything to one plot call so that Plots will a,lways cycle the colors correctly I think.

That is not what was written, but color=[:red :blue]

Note that in Plots.jl, the difference betwen vectors and matrices is crucial.

Ahhh, yes indeed. Now I also remember reading an article in the docs of Plots.jl explaining exactly this difference. Sorry!

[:red :blue] (1x2 Matrix) will cycle through red and blue for series.

[:red, :blue] (2 element Vector) will use both colors for one series.

Thanks!

EDIT: Here is the corresponding section from the Plots.jl documentation.

1 Like

This generalizes a bit my comment further above:

n = length(unique(test_data.category))
colors = palette(:default)[1:n]'

then just add the following argument to the plots commands:

 color=colors
1 Like