Grouped error bars change position after saving figure

4 views (last 30 days)
I have a grouped bar graph with error bars (3 groups, 5 bars each, 15 bars and error bars total). When the figure is first created, the plot looks fine, but when I save (using file>saveas in the figure window) and repoen the figure, the error bars move from being centered on their respective bars (correct) to being centered on each group (incorrect). I've scowered the figure and errorbar property lists for a setting that might prevent this with no luck and there doesn't seem to be any other posts here that address this issue either.
Code
barHeights = [0.954, 0.666, 0.604, 0.842, 0.662;...
0.021, 0.280, 0.259, 0.145, 0.212;...
0.027, 0.075, 0.100, 0.022, 0.084];
barErrors = [0.023, 0.057, 0.091, 0.056, 0.081;...
0.007, 0.046, 0.080, 0.053, 0.091;...
0.018, 0.029, 0.029, 0.016, 0.034];
[nGroups,nBars] = size(barHeights);
groupNames = categorical("Group" + string(1:nGroups));
barNames = "Bar" + string(1:nBars);
figure;
hold on
b = bar(groupNames,barHeights,'FaceColor','flat');
title("Title");
xlabel("xlabel");
ylabel("ylabel");
grid on;
x = reshape([b.XEndPoints],[nGroups,nBars]);
errorbar(x,barHeights,barErrors,'k','linestyle','none');
legend(barNames);
hold off
Figure: Before Saving (CORRECT)
Figure: After Saving and Reopening (INCORRECT)
  1 Comment
Andrew Soltisz
Andrew Soltisz on 18 May 2021
Edited: Andrew Soltisz on 18 May 2021
I notice that when I set the error bar 'XDataMode' of the correct/original figure from 'manual' to 'auto', the error bars move from their bar-centered positions to the group-centered positions, and restoring the 'XDataMode' to 'auto' does not return the error bars to their original bar-centered positions. Additionally, the error bars of the incorrect figure also have their 'XDataMode' set to manual, leading me to think that the figure saving-and-reopening process somehow sets the 'XDataMode' to 'auto' and then back to 'manual', causing the error bars to lose their bar-centered positions. I have no idea how to prevent this.

Sign in to comment.

Accepted Answer

Adam Danz
Adam Danz on 18 May 2021
Edited: Adam Danz on 21 Feb 2023
The problem is caused by assigning numeric x-values to the errorbars on a categorical x-axis. The errorbar function works around the difference in axis ruler types but when the figure is generated again by opening the figure the x-values of the errorbars are assigned to the categorical x-values.
In fact, if you look at the XData values of the errorbars after they are generated, their values are actually the categorical x-values. It's surprising the errorbars are positioned in the right place to begin with.
ebh =errorbar(x,barHeights,barErrors,'k','linestyle','none');
ebh.XData
ans =
1×3 categorical array
Group1 Group2 Group3
ans =
1×3 categorical array
Group1 Group2 Group3
ans =
1×3 categorical array
Group1 Group2 Group3
ans =
1×3 categorical array
Group1 Group2 Group3
ans =
1×3 categorical array
Group1 Group2 Group3
Instead of using a categorical x-ruler, use a numeric x-ruler and set the tick labels,
barHeights = [0.954, 0.666, 0.604, 0.842, 0.662;...
0.021, 0.280, 0.259, 0.145, 0.212;...
0.027, 0.075, 0.100, 0.022, 0.084];
barErrors = [0.023, 0.057, 0.091, 0.056, 0.081;...
0.007, 0.046, 0.080, 0.053, 0.091;...
0.018, 0.029, 0.029, 0.016, 0.034];
[nGroups,nBars] = size(barHeights);
%groupNames = categorical("Group" + string(1:nGroups));
barNames = "Bar" + string(1:nBars);
figure;
hold on
b = bar(barHeights,'FaceColor','flat'); % REMOVE THE CATEGORICAL X-VALUES
title("Title");
xlabel("xlabel");
ylabel("ylabel");
grid on;
x = reshape([b.XEndPoints],[nGroups,nBars]);
errorbar(x,barHeights,barErrors,'k','linestyle','none');
% SET THE TICKS AND TICKLABELS
set(gca, 'XTick', b(1).XData, 'XTickLabel', "Group" + string(1:nGroups))
legend(barNames);
hold off
If you're using a MATLAB release prior to R2019b, compute x using x=b(1).XData'+[b.XOffset];
  3 Comments
Samy Alkhayat
Samy Alkhayat on 18 Feb 2023
Hello Adam,
I have the same issue, I know your code works on MATLAB 2019 and later, but I have 2018 version.
It seems I need a replacement for
x = reshape([b.XEndPoints],[nGroups,nBars]);
in MATLAB 2018, any tips?
Thanks in advance!

Sign in to comment.

More Answers (0)

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!