4

Is there a (manual or automatic) way of cutting out several parts of the y-axis for certain x-values in a Matlab plot? I found solutions in other programming languages (see 2 links below), but not for Matlab, except for BreakAxis and BreakYaxis on File Exchange, but this only works for one break.

I am also posting my code below, for which I would like to implement it. I would like to have a y-axis break for each yNegData and yPosData, i.e. two breaks, each at [0.3*min(yNegData) 0.7*min(yNegData] and [0.3*max(yPosData) 0.7*max(yPosData].

If you could write it in a way that I could use it for different kinds of plots (not only bar, but also line, for example), that would be very useful.

http://lagrange.univ-lyon1.fr/docs/matplotlib/examples/pylab_examples/broken_axis.html

Using gnuplot, how to 'cut out' usused y-axis regions of the graph

The code:

revenue = ones(100,1);
opex = -1*ones(100,1);
opex(10:15,1) = 3;

data{1} = revenue;
data{2} = opex;
colors = parula(numel(data));
labels = {'Revenue','Opex'};
for i = 1:numel(data)
    dataNeg{i} = data{i};
    dataNeg{i}(data{i}>0) = 0;
    dataPos{i} = data{i};
    dataPos{i}(data{i}<0) = 0;
    mdata(i) = nnz(dataPos{i});  % was: mean(data{i});
end
[~,posOrder] = sort(mdata,'ascend');
[~,negOrder] = sort(mdata,'descend');
yDataPos = [dataPos{posOrder}];
yDataNeg = [dataNeg{negOrder}];
hold on;
bNeg = bar(yDataNeg,'stack');
bPos = bar(yDataPos,'stack');
for i= 1:numel(data)
    set(bNeg(i),'FaceColor',colors(negOrder(i),:))
    set(bPos(i),'FaceColor',colors(posOrder(i),:))
end
legend(labels{:});
hold off;
gehbiszumeis
  • 3,525
  • 4
  • 24
  • 41
LenaH
  • 313
  • 2
  • 14
  • 2
    Why do you want a broken axis? In science it's not used often, since it distorts the visual ratio between peaks, e.g. the two peaks in the first link you provided look a lot smaller due to the cut y-axis, leading to a misrepresentation of your data. Why not use a logarithmic plot instead? – Adriaan Jul 22 '19 at 09:00
  • 1
    Not exactly a duplicate, but you can get inspiration from this question and my answer to it: [Multiple axis breaks](https://stackoverflow.com/questions/29975336/multiple-axis-breaks/29977988#29977988) – Hoki Jul 22 '19 at 09:12
  • 1
    @Adriaan `<-` **This x10**. If your plot doesn't clearly show your data, use a different plot, don't make it less clear! – Wolfie Jul 22 '19 at 10:10
  • Adriaan, my data is actually very different from the one in the link and in my case it makes sense, logarithmic would not. Also note that my code contains only dummy data. @Hoki thank you! I tried but couldn't adjust your code to fit my data. I would like to have a split for each yDataNeg and yDataPos. Do you have a hint how? – LenaH Jul 22 '19 at 12:04
  • 1
    @LenaH then maybe making three sublots instead, i.e. one for each "cut-out" part, would make more sense? You can then adjust the distance between subplots if you want them closer to one another. See e.g. [this answer](https://stats.stackexchange.com/a/358706/215553) – Adriaan Jul 22 '19 at 12:13
  • No, that's unfortunately not working for my data either. – LenaH Jul 22 '19 at 12:52
  • 1
    Sorry I didn't notice that you were using `bar` graph. My example is a hack which make use of `NaN` to break a `line`, this is impossible to do with a built in `bar` graph. You would have to write your own `bar` routine if you want to achieve that. Quite a heavy job I would anticipate... – Hoki Jul 23 '19 at 10:41
  • Another possible hack (which I'm not going to write full code for it) is to take a _picture_ of your figure (using `getframe`), then you can cut bands from your image, join the remaining parts, then draw the break symbols at the proper locations... – Hoki Jul 23 '19 at 10:47
  • 3
    You should **never ever** cut a bar graph. A bar graph encodes values in the height of the bar. The bar has to start at 0 and not be cut for that to be true. A cut bar graph is a great way to lie to your readers. All axes with a cut in them are bad, but in a bar graph it is truly evil. You need to find a better way of showing your data. If you share what data you want to show, I could help you find a good way to show it. – Cris Luengo Sep 10 '19 at 13:31
  • instead of showing example of `line` plots, you'd better show an example of bar graph with a cut if that's what you're after. [example](https://peltiertech.com/images/2011-11/Ybroken.png) – Hoki Sep 12 '19 at 17:34
  • 1
    @CrisLuengo there's a usage case for exactly this in quite a lot of media nowadays (unfortunately) – LTPCGO Sep 17 '19 at 03:52

1 Answers1

2

There is this package

https://nl.mathworks.com/matlabcentral/fileexchange/45760-break-y-axis

which works for lines; it has a little example

a=20*rand(21,1)+10;
figure;hold on;
plot(a);
breakyaxis([14 21]);
% hold off %% I guess, inserted by me

However, it does not seem to work as well for bar plots -- if you replace plot(a) by bar(a) in the example above the split stripe does not cover the width of the axes. It could be tweaked I'm sure but that might not be worth the effort.

If you're OK with switching to R you can use gap.barplot() from the plotrix package (see this example) and you can also still switch to gnuplot (see this example).

alle_meije
  • 2,424
  • 1
  • 19
  • 40