version 1.0.0.0 (1.69 KB) by
Evan

Generate a bar plot with multiple stacks grouped together.

Plot a set of stacked bars, but group them according to labels provided.

Params:

stackData is a 3D matrix (i.e., stackData(i, j, k) => (Group, Stack, StackElement))

groupLabels is a CELL type (i.e., { 'a', 1 , 20, 'foo' };)

Evan (2021). Plot Groups of Stacked Bars (https://www.mathworks.com/matlabcentral/fileexchange/32884-plot-groups-of-stacked-bars), MATLAB Central File Exchange. Retrieved .

Created with
R2008b

Compatible with any release

**Inspired:**
Machine Learning with MATLAB

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

Start Hunting!Create scripts with code, output, and formatted text in a single executable document.

Rodrigo BezerraGreat job. Works perfectly.

Dilini Wickrama Achchigehaibin niunice！thank you！

Christie EtukudorStill very relevant; thank you

Loughlin DUDLEYEleonora GajettiPierre-Emmanuel Omsthank you works great !!

Vasia Papoutsakithank you!

P.V.Adam DanzThe handle to the bars should be added as an output so users can manipulate the bar parameters.

Here's an example how to change the color of segments within each stack.

https://www.mathworks.com/matlabcentral/answers/371186-grouped-stacked-bar-with-specific-colours#answer_393160

Hanno Teiweszhang mengFrancisco Javier Hernandez SantiagoOnce you plot the data, you can easily customize the figure using "Figure Properties" from the "edit" ,enu. For instance, colors, name or scale (linear or log).

liu xiaomanthank you very much!

justokMarina CostantiniQiquan Zhanghow to add legend? thank you very much! i am hurry

Qiquan Zhanghow to work?

Pushpa Dissanayakethanks for your contribution, it's useful!

MattePUseful but a question.

How can I increase the distance between the x-tick label (to lable the groups) and the x-tick lebels (to lable the elements of the group)?

Itamar CohenGreat and very useful. 10x.

Marleen CobbenThanks! Also for the color coding Tim!

Alessandro RigazzikateclLabels for individual bars are on the top b/c the Y coordinate for that text is set to the sum of all the columns. To label underneath the bars (and just under the line marking the x-axis), change the added code starting at line 36 to

for j=1:NumGroupsPerAxis

text(groupDrawPos(j),0,...

barLabels{i},'VerticalAlignment','cap',...

'HorizontalAlignment','center');

end

xyzmrsirthanks

Alexandre MangotIn response to the multiple comments regarding add label to individual bars, it appears that the labels is always shown at the top of the bars even though 'Bottom' was set for 'VerticalAlignment' - any reason why?

Andreas AlbrechtAdding the following line inside the for-loop does avoid unnecessary legend entries if you padded your data with zeros before calling this function.

Y = Y(:,any(Y,1));

Harish SuryanarayanaCHENHAO WANGAnjum Rauf MeerTasnuba SiddiquiCompletly worked :), thank you for the awesome coding and sharing.

Patricia StahnpaulaThanks, useful.

Michail SchwabIkram AshrafThanks, could you please tell me how to do:

i) How to increase the bar width seems that even setting the MaxGroupWidth = 1 it does not increase much.

ii) How to bring each label in the center of bars.

Thanks.

YI GU?add bar labels it work

function plotBarStackGroups(stackData, groupLabels)

%% Plot a set of stacked bars, but group them according to labels provided.

%%

%% Params:

%% stackData is a 3D matrix (i.e., stackData(i, j, k) => (Group, Stack, StackElement))

%% groupLabels is a CELL type (i.e., { 'a', 1 , 20, 'because' };)

%%

%% Copyright 2011 Evan Bollig (bollig at scs DOT fsu ANOTHERDOT edu

%%

%%

NumGroupsPerAxis = size(stackData, 1);

NumStacksPerGroup = size(stackData, 2);

% Count off the number of bins

groupBins = 1:NumGroupsPerAxis;

MaxGroupWidth = 0.65; % Fraction of 1. If 1, then we have all bars in groups touching

groupOffset = MaxGroupWidth/NumStacksPerGroup;

figure

hold on;

for i=1:NumStacksPerGroup

Y = squeeze(stackData(:,i,:));

% Center the bars:

internalPosCount = i - ((NumStacksPerGroup+1) / 2);

% Offset the group draw positions:

groupDrawPos(i,:) = (internalPosCount)* groupOffset + groupBins;

h = bar(Y, 'stacked');

set(h,'BarWidth',groupOffset);

set(h,'XData',groupDrawPos(i,:));

end

barLabels={'2000','2005','2010','2015'};

% Bar Labeling

for j=1:NumGroupsPerAxis

text(groupDrawPos(:,j),squeeze(sum(stackData(j,:,:),3)),...

barLabels,'VerticalAlignment','bottom',...

'HorizontalAlignment','center');

end

hold off;

set(gca,'XTickMode','manual');

set(gca,'XTick',1:NumGroupsPerAxis);

set(gca,'XTickLabelMode','manual');

set(gca,'XTickLabel',groupLabels);

end

Reinhard KreuzerKumushThanks Evan! This is great ;-) I was wondering if there is a way to have log-scale on the y-axis? My groups are super heterogeneous, and I would like to plot them as logs (with base 10) against powes of 10 on the vertical. Many thanks.

Konstantinos TsitsilonisVery useful function!

Figured out a solution for the labelling of individual columns:

Add as an input a cell array of strings:

barLabels={'column1name','column2name',etc...};

Then, on line 36, just before the 'end' of the for loop add the following lines:

% Bar Labeling

for j=1:NumGroupsPerAxis

text(groupDrawPos(j),sum(Y(j,:),2),...

barLabel{i},'VerticalAlignment','bottom',...

'HorizontalAlignment','center');

end

ys chenThanks, very handy function!

Eunice LiruffntuffHi, trying to add legend. Plot working as expected otherwise.

Looking at Beckah Rieck's post on 12 July '16, first step is to create a handle but...

Data

Z(:,:,1) = [EnCol'*2, EnAddDiurn'];

Z(:,:,2) = [zeros(12,1), EnAddSeas'];

(all variables are 12x1 doubles as you can see form zeros value)

Cmd to create handle

b = plotBarStackGroups(Z, months);

Error

Error using plotBarStackGroups

Too many output arguments.

Do you see what I'm doing wrong here?

Thanks in advance!

Alexander KurzThanks for this Evan! Finally I would like to plot groups of stacked bars with error bars. Anyone already did it before?

regaieg rymHi

I want to produce the stackData matrix by my own values. Any ideas ?

Suehee HuhThanks!!!!

Beckah RieckThanks Evan!

Emma- if you are talking about x-labels for what each bar means, just add a legend:

b = plotBarStackGroups(stackData, Month);

legend([b(1,1), b(2,1), b(2,2)], 'Total Added', 'Closed- Non Quick Hits', 'Closed- Quick Hits');

If you mean Y data labels on the bars, use text:

text(b(1,1).XData', zeros(size(b(1,1).XData')), labelsAddedtoQ);

(that places them at the base).

Ashrar MatinEmma JonassonThanks for the script. I would also like to add x-labels for each bar within the groups, anyone who can help me achieve that? Explaining from the example: above the label 'Test', I would like to add labels on the bars, e.g. 'a' 'b' 'c', and so on.

Emma JonassonSamythanks for the script, if you don't like the border of the plot being messed up just remove the 'hold on;' in line 20 and add 'if i == 1, hold on; end' after 'h(i,:) = bar(Y, 'stacked');'!

tan yuElizabethOleg KomarovIf you have a 3D array A, then reshaping your array and interleaving groups with a row of NaNs will produce the same result:

sz = size(A);

B = [A, NaN(sz(1),1,sz(3))];

B = reshape(permute(B, [2,1,3]),sz(1)*(sz(2)+1),sz(3));

bar(C(1:end-1,:),'stacked')

ADITHYANWorks very well. Thanks a lot evan.

Daniel PaivaVery good.

JennyVeraRicardoVery useful function!, thank you!

TimBerk, I had the same desire and found it was pretty simple to customize.

After this...

h(i,:) = bar(Y, 'stacked');

I added this...

set(h(i,1),'facecolor','y','edgecolor','k');

set(h(i,2),'facecolor','r','edgecolor','k');

set(h(i,3),'facecolor','c','edgecolor','k');

set(h(i,4),'facecolor','g','edgecolor','k');

...so that the base of each bar is always yellow, etc.

Doubt you'll need this 1 year later, but for the next rookie like myself, could be useful.

Thanks for the elegant and useful function, Evan.

BenBerkThanks, very handy function!

Could you please tell whether we can assign different colors to different stacks?

Currently, all the stack elements have the same color/type. However, I am wonering whether it would be possible to differentiate the different stacks?

BerkgregaNice one! Works! Example makes it clear! Thank you!

EvanExample usage:

NumStacksPerGroup = 3;

NumGroupsPerAxis = 6;

NumStackElements = 4;

% labels to use on tick marks for groups

groupLabels = { 'Test'; 2; 4; 6; 8; -1; };

stackData = rand(NumGroupsPerAxis,NumStacksPerGroup,NumStackElements);

plotBarStackGroups(stackData, groupLabels);

set(gca,'FontSize',18)

set(gcf,'Position',[100 100 720 650])

grid on

set(gca,'Layer','top') % put grid lines on top of stacks