Put Y-Ticks above bars in stacked horizontal bar chart

2 vues (au cours des 30 derniers jours)
AEdel
AEdel le 15 Fév 2024
Commenté : Adam Danz le 18 Fév 2024
Hello everyone,
I am trying to make a stacked horizontal bar chart. As my y-ticks are rather long strings, I would like to place them above the respective bars. I tried it with the annotation function, but did not succeed. Where am i going wrong? Or is there another way of doing this?
I also want the bars to display the values of each bar (that I have managed)
y = [30 70; 20 80; 60 40];
b = barh(y, 'stacked','BarWidth',0.3);
% set y-axis tick labels
yticks(1:size(y, 1));
yticklabels({'Some very long question', 'Some more text', 'Even more text'})
% adjust tick label position
yPos = 1:size(y, 1);
barValues = sum(y, 2);
for i = 1:length(yPos)
annotation('textbox', [barValues(i) yPos(i)-0.2 0 0], 'String', num2str(barValues(i)),'VerticalAlignment', 'middle', 'HorizontalAlignment', 'left', 'FontSize', 10)
end
% insert values into each bar
for i=1:length(b)
for j = 1:length(b(i).YData)
y = b(i).YEndPoints(j) - (b(i).YData(j)) / 2;
s = sprintf('%.0f', b(i).YData(j));
text(y', b(i).XData(j), s);
end
end
% adjust other properties
title('The distribution of answers to each question');
legend('percentage of answer A', 'percentage of answer B');
Thank you for helping me out.

Réponse acceptée

Austin M. Weber
Austin M. Weber le 16 Fév 2024
Modifié(e) : Austin M. Weber le 16 Fév 2024
One option would be to use the text function:
y = [30 70; 20 80; 60 40];
b = barh(y, 'stacked','BarWidth',0.3);
labels = {'Some very long question', 'Some more text', 'Even more text'};
% Add labels above the bars
hold on
text(50, 1.25, labels(1),'HorizontalAlignment','center')
text(50, 2.25, labels(2),'HorizontalAlignment','center')
text(50, 3.25, labels(3),'HorizontalAlignment','center')
hold off
set(gca,'YTick',[]) % Get rid of exterior ytick marks

Plus de réponses (1)

Adam Danz
Adam Danz le 16 Fév 2024
Modifié(e) : Adam Danz le 16 Fév 2024
Annotations are tricky because they rely on coordinates that are normalized to the figure area rather than using data units.
If you're adding text at specific locations in axes, use text.
This solution also vectorizes the bar labels instead of using a loop.
y = [30 70; 20 80; 60 40];
b = barh(y, 'stacked','BarWidth',0.3);
xStr = vertcat(b.XData)';
yStr = vertcat(b.YEndPoints)' - y/2;
str = string(y);
text(yStr(:),xStr(:),str(:),...
'HorizontalAlignment','Center',...
'VerticalAlignment','Middle', ...
'Color','w')
ylabs = {'Some very long question', 'Some more text', 'Even more text'};
ylabPos = b(1).XData + b(1).BarWidth/2;
xlabPos = b(1).BaseValue .* ones(size(ylabPos));
text(xlabPos, ylabPos, ylabs, ...
'HorizontalAlignment','left', ...
'VerticalAlignment','bottom')
yticklabels([])
  3 commentaires
Austin M. Weber
Austin M. Weber le 18 Fév 2024
Great question! Programmatically speaking, I would say that Adam's solution is superior because it can be easily applied to charts that have many data bars.
But, if you are creating a bar plot with only 3 bars, my solution takes fewer lines of code and may be easier to read for those who are less experienced with MATLAB syntax.
If you want to plot more than three bars using my solution, you would likely want to wrap the text function in a for-loop. Vectorizing your code (as Adam's solution demonstrates) is technically faster than a for-loop, but for simple plots like this you can decide whether you prefer the simpler solution or the optimized one. Both will work just fine.
Adam Danz
Adam Danz le 18 Fév 2024
@AEdel It's great that you're engaging with different solutions and considering the options. Both approaches have their merits..
Regarding my solution, I've leveraged some of the bar properties to generalize the solution. For example, the vertical position of the text is computed using the XData and BarWidth properties instead of hard-coding the vertical position. This way, the solution can be applied to other bar charts that may have different bar widths. The horizontal position of the text is based on the BaseValue value which defines where the bars 'start'.
That said, it's always encouraging to see diverse approaches.

Connectez-vous pour commenter.

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by