3

So I need to plot some errobar plots in a figure. Specifically I need 4 errorbar plots in each figure, the problem is that the figure gets a bit unreadable when several data is plotted.

Example:

clear all
close all
clc



x = 0:pi/10:pi;
y = sin(x);
y2=cos(x);
y3=atan(x);
e = std(y)*ones(size(x));
e2 = std(y2)*ones(size(x));
e3 = std(y3)*ones(size(x));

figure
hold on
errorbar(x,y,e)
errorbar(x,y2,e2)
errorbar(x,y3,e3)

enter image description here

My idea to solve the problem is to fill the area that the corners of the errorbars delimit with the same color of the plot and low alpha, so the overlapping of the areas is visible.

The problem is that the only way I can imagine of doing this is to create a mesh in the area delimited by the errorbar corners and then fill them with patch. This is indeed possible, but quite annoying, as a plot will not have a convex hull, therefore I will need to iteratively go creating the triangles one by one. So the question is : Is there a more elegant way of doing this?

Additionally, I am open to suggestions of a better way of visualizing this data, if anyone has.

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
Ander Biguri
  • 35,140
  • 11
  • 74
  • 120
  • You could use the SEM instead of the standard deviation as error bars :) Seriously that's a very interesting question! – Benoit_11 Feb 17 '15 at 10:28
  • @Benoit_11 Thanks! About the SEM: You are saying that its better to use the SEM while plotting the data statistically or that I should use the same as descriptor of the data? I got those std from the Matlab example! (aah this Matlab examples) – Ander Biguri Feb 17 '15 at 10:36
  • 1
    Oh i think using the std is fine; in my field of work people tend to use the sem because the errors look smaller and their data more solid haha. – Benoit_11 Feb 17 '15 at 10:43
  • 1
    @Benoit_11 Statistics is the field where you can cheat while still being scientifically correct hehe. – Ander Biguri Feb 17 '15 at 10:44
  • Something that I come to think of is, while not entirely correct, to have a minor shift in x for the errorbars for the different plots. So to say, the errorbar get the same range, but shifted (let us say) 0.03 units to either side for the-x coordinate. The value 0.03 must of course be placed in relation to the rest so you would need to have a quota between the number of errorbars, the range of x and also the wanted displacement I guess. – patrik Feb 17 '15 at 12:31
  • @patrik That works for a small amount of errorbars, but not for a big one. If you run the example with `x = 0:pi/40:pi` then it will just get way more chaotic. That's why I was hopping to put fill the are where the errors are, instead of even putting errorbars. – Ander Biguri Feb 17 '15 at 12:46
  • Are you using R2014b? – Luis Mendo Feb 17 '15 at 13:02
  • @LuisMendo Yup (see tag). – Ander Biguri Feb 17 '15 at 13:02
  • I read too fast, as usual :-) – Luis Mendo Feb 17 '15 at 13:03
  • You could actually try with thicker lines here. It would not remove your problem, but the individual colors would appear better. Try it and see how it looks. – patrik Feb 17 '15 at 14:19
  • @patrik It has the same problem of more amount of data. I will post ASAP a real example of my data in the post so a real example is shown (computer is doing lung maths now) – Ander Biguri Feb 17 '15 at 14:32

1 Answers1

5

Approach 1

Plot the graphs normally, and then plot the errorbars manually using patches. The data for the patches (coordinates and color) is taken from the plotted graphs, and the alpha of the patch can be set to any desired value.

clear all
close all
clc

error_alpha = .4;
error_width_factor = .01;

x = 0:pi/10:pi;
y = sin(x);
y2 = cos(x);
y3 = atan(x);
e = std(y)*ones(size(x));
e2 = std(y2)*ones(size(x));
e3 = std(y3)*ones(size(x));
ee = [e; e2; e3];

figure
hold on
hp(1) = plot(x,y);
hp(2) = plot(x,y2);
hp(3) = plot(x,y3);

w = diff(xlim)*error_width_factor;
for m = 1:numel(hp)
    for n = 1:numel(hp(m).XData)
        patch(hp(m).XData(n)+[-1 1 1 -1]*w, hp(m).YData(n)+[-1 -1 1 1]*ee(m,n), 'w',...
           'FaceColor', hp(m).Color, 'FaceAlpha', error_alpha, 'EdgeColor', 'none');
    end
end

enter image description here

Approach 2

Similar as before, but use narrower patches and plot them with a graph-dependent horizontal shift (as suggested by @Patrik). Applying an alpha value helps keep the figure lighter.

The code is a modified version of that of approach 1. The example shown here contains 101 data values, and is still rather visible.

clear all
close all
clc

error_alpha = .4;
error_width_factor = .003;

x = 0:pi/50:pi;
y = sin(x);
y2 = cos(x);
y3 = atan(x);
e = std(y)*ones(size(x));
e2 = std(y2)*ones(size(x));
e3 = std(y3)*ones(size(x));
ee = [e; e2; e3];

figure
hold on
hp(1) = plot(x,y);
hp(2) = plot(x,y2);
hp(3) = plot(x,y3);

w = diff(xlim)*error_width_factor;
m0 = (numel(hp)+1)/2;
for m = 1:numel(hp)
    for n = 1:numel(hp(m).XData)
        patch(hp(m).XData(n)+[-1 1 1 -1]*w+w*(m-m0),...
        hp(m).YData(n)+[-1 -1 1 1]*ee(m,n), 'w', 'FaceColor', hp(m).Color, ...
        'FaceAlpha', error_alpha, 'EdgeColor', 'none');
    end
end

enter image description here

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • Quite an interesting approach. I am going to try it with more complex data, to see how it fits. – Ander Biguri Feb 17 '15 at 13:40
  • A suggestion for a different approach: you could perhaps use lines instead of patches, without alpha, and slightly _shift horizontally_ lines corresponding to different graphs, so that they con't coincide – Luis Mendo Feb 17 '15 at 13:41
  • That was suggested in previous comments. But if you try that with `x = 0:pi/50:pi;` you'll quicly understand why it doesn't always work. Thats why I though about the whole area patch thing. – Ander Biguri Feb 17 '15 at 13:43
  • 1
    @AnderBiguri Do not get me wrong. I liked the answer and upvoted it, but want to give a warning. I fear that, if the data is too messy this may be misleading (and data tend to be messy). I see some tendencies of this already for this data. The orange parts is hard to recognize due to the red and the sharp contrast of the other data. If a forth line was it would be even worse. The reader would then have to find out which color corresponds to which plot, and there would be a lot of colors. That may work for a report, but for a presentation it may be too complicated. – patrik Feb 17 '15 at 14:14
  • 1
    @patrik You are completely right. I like the answer also, and I up-voted it, but I want to make sure that this approach will work with some more complex data. I will test it with my own data and see if this answer is more clear always or only with simpler data. It is difficult to measure "visual clarity". I want this plots for a journal article (hopefully), so they need to be clear. – Ander Biguri Feb 17 '15 at 14:23
  • I agree with both of you. The colors of the patches get messed up easily – Luis Mendo Feb 17 '15 at 14:45
  • @patrik Sorry, I hadn't seen your earlier suggestion of a horizontal shift – Luis Mendo Feb 17 '15 at 14:48
  • I've added the horizontal shift (with due credit to @Patrik). Combined with a medium value for alpha, I think the result is not so bad – Luis Mendo Feb 17 '15 at 15:01
  • @LuisMendo No problem, and good nicely done to realize it. Imo, this one looks better than the first one, but of course OP should decide that for himself. – patrik Feb 17 '15 at 16:28
  • @patrik Definetly the second one is better, and it gives quite good visual impression using more complex data. Fantastic answer by Luis. – Ander Biguri Feb 18 '15 at 13:59
  • 1
    @AnderBiguri Glad it worked! For more complex data I guess you can reduce `error_width_factor`, and perhaps `error_alpha`, for better results – Luis Mendo Feb 18 '15 at 16:01