How to plot mean +/- deviation in Plots.jl?

Consider the example below:

using Plots

xs = linspace(1,100)
μs = log.(xs)
σs = rand(length(xs))

plot(xs,μs,grid=false,yerror=σs)

Is there any way to replace the error bars by a shaded transparent area with the same color as the mean or lighter?

Something like what we usually have in Gaussian Processes illustrations, but relating the color of the shaded area to the mean:

3 Likes

:ribbon
For some functions you could also check groupapply in StatPlots

2 Likes

To get the ribbon in a specific color but ‘lighter’, use the same color but set fillalpha to less than 1.

1 Like

Thanks @mkborregaard, where do I pass :ribbon in the plot command?

Can you share a working example based on the one I started?

For future reference, this is the solution:

using Plots

xs = linspace(1,100)
μs = log.(xs)
σs = rand(length(xs))

plot(xs,μs,grid=false,ribbon=σs,fillalpha=.5)

Thank you @mkborregaard.

41 Likes

Is it possible to plot an “error” that asymmetric around the “mean”? That is, I want to plot the ribbon around the line f(x) with the error interval [f(x) - err1(x), f(x) + err2(x)], where err1(x) != err2(x).

1 Like

ribbon = (err1(x), err2(x))

4 Likes

Sorry for reviving this thread, but I believe this question falls nicely into this topic.

I can’t seem to be able to display asymmetric error bars in scatter plots. Is there a way?
Something along these lines:

a = 1:10
b = randn(10)
med_b = median(b)
scatter((a, med_b),
		yerror=(med_b-minimum(b),
				maximum(b)-med_b))
1 Like

That should more or less work but med_b, minimum(b) etc are just scalars. a is a vector. Are you sure this is what you want?

Sorry @mkborregaard , I made some last minute changes to the MWE and broke it. It should just be:

a = 0.0
b = randn(10)
med_b = median(b)
max_b = maximum(b)
min_b = minimum(b)
scatter((a, med_b),
		yerror=(med_b-min_b,
				max_b-med_b))

Which gives me

unexpected ebi type Array{Tuple{Float64,Float64},0} for errorbar: (1.6075403984383283, 1.2973639900098863)

However, since you mentioned it, I decided trying this out with vectors and it indeed works.

a = 1:10
b = [randn(10) for _ in a]
med_b = [median(x) for x in b]
max_b = [maximum(x) for x in b]
min_b = [minimum(x) for x in b]
scatter((a, med_b),
		yerror=(med_b-min_b,
				max_b-med_b))

This gives me what I want.

But now I’m not sure what I’m missing in the first MWE.

You’re not supposed to plot scalars, I think that’s it

Yeah, that’s what I thought for a while as well.

Until I decided to give this a shot

a = 0.0
b = randn(10)
med_b = median(b)
max_b = maximum(b)
min_b = minimum(b)
scatter((a, med_b),
		yerror=[(med_b-min_b,
				max_b-med_b)])

and it works. Kind of unintuitive at first, having to wrap a tuple into an array, given that when working with arrays it’s the other way around.

Either way, problem solved.

Building on this example, is there a way to ensure that the label for the plot uses the marker “shape” and not the “ribbon” color? Use case is when printed (black and white), it’s still clear which label goes with which line. Example below, label is tied to ribbon color, not marker shape.

pyplot()
xs = range(1,20,step=1)
μs1 = log.(xs)
σs1 = rand(length(xs))
μs2 = log10.(xs)
σs2 = rand(length(xs))

Plots.plot( xs,μs1,grid=false,ribbon=σs1, shape=:circle, label=“μs1”)
Plots.plot!(xs,μs2,grid=false,ribbon=σs2, shape=:square, label=“μs2”)

Could you show what the problem looks like? Running your code with the GR backend (I don’t have pyplot), I get:

image

which looks to me like the legend uses the marker shape? If you’re seeing something different it might be a backend-specific issue.

Yes, it must be backend. Here’s what it looks like with pyplot:fig_ribbon_label

This workaround seems to work in Julia PyPlot:

using Plots; pyplot()
xs = range(1,20,step=1)
μs1, σs1  = log.(xs), rand(length(xs))
μs2, σs2 = log10.(xs), rand(length(xs))
Plots.plot( xs,μs1, color=:lightblue, ribbon=σs1,label=false)
Plots.plot!(xs,μs2, color=:pink, ribbon=σs2,label=false)
Plots.plot!(xs,μs1, color=:blue, marker=(:circle, 8, 1.), label="μs1")
Plots.plot!(xs,μs2, color=:red, marker=(:square, 8, 1.), label="μs2")

1 Like

I don’t manage to plot asymmetric error using ribbon. Is this an expected outcome or a bug?

The examples provided here do work fine for both Plots.jl gr() and pyplot() backends:

Plots.plot( xs,μs1, color=:lightblue, ribbon=(σs1,σs1/3),label=false)

asymmetric_gr_ribbon

3 Likes

Possibly the issue arises using StatsPlots @df macro. I have all my errors in one dataframe column where each entry is a tuple. I guess this is why doesn’t work in general. However it seems to be fine with Plotlyjs

@Dario_Sarra, please provide a MWE.