2
votes

I have a tricky question, which I think cannot be simply answered.

I have a large data table and want to save bar charts for each 2 corresponding mean values. I already did that with "for loop", but I cannot set different colors to my bars and cannot set proper spaces between bars and axes.

That's the simplest example:

k = [2 5]
bar(k)

Two bars on one plot

Matlab thinks about those data [2 5] as about one "group" and it does not give a possibility of changing color for only one bar.

Of course, when we have different "groups", colors are changeable.

y = bar([1 2 3; 4 5 6]);
y(2).FaceColor = 'red';

But what about my example? I need only two bars, and I need to color them differently. Also, I want to set a small space between each bar and the axes (and again with two bars it is not that simple, and I cannot use "bar width" because that doesn't give me what I really want).

Does anyone know how to get around this?

Thanks for any reply! Mary

4
What do you mean by spacing from the axes? which axis? x, y or both?EBH

4 Answers

0
votes

A good trick could be add zero column for each group:

k = [2 5;0 0];
bar(k,'grouped')

UPDATE

Another solution to have different color could be using location in bar:

k = [2 5];
figure(1);
hold on;
h=bar(1,k(1));
set(h,'FaceColor','k');
h=bar(2,k(2));
set(h,'FaceColor','b');
hold off
0
votes

As far as I know, this requires the use of a custom bar plot, since Matlab's barplots use dynamic colormaps. Personally, I like the GRAMM toolbox for all these customizations: [GRAMM on file-exchange] [GRAMM on github].

Here's an example:

Bar width

x = [1 2];
y = [1 1.5];
c = x;
custom_map = ...
[1 0.3673 0.4132;
 0 0.7375 0.8344];

clear g
g(1,1)=gramm('x',x,'y',y,'color',c);
g(1,1).geom_bar('width',0.2);
g(1,1).set_title('Width = 0.2');

g(1,2)=gramm('x',x,'y',y,'color',c);
g(1,2).geom_bar('width',0.8);
g(1,2).set_title('Width = 0.8');

g.set_names('y','','x','');
g.set_color_options('map',custom_map);
g.axe_property('YTick',[],'LineWidth',1,'YColor',[1 1 1],'XLim',[0.5 2.5],'XTick',[1 2])

figure('Position',[100 100 600 300]);
g.draw();
0
votes

The histogram function is one option that will easily handle the spacing and x-axis labeling, but you'll have to plot each bar separately to independently control the colors:

k = [2 5];
histogram('Categories', {'ONE'}, 'BinCounts', k(1), 'BarWidth', 0.8, ...
          'FaceAlpha', 1, 'FaceColor', [0 0.4470 0.7410]);
hold on;
histogram('Categories', {'TWO'}, 'BinCounts', k(2), 'BarWidth', 0.8, ...
          'FaceAlpha', 1, 'FaceColor', [0.8500 0.3250 0.0980]);

enter image description here

0
votes

Here is an option to workaround this. You can use diag(k) to create a 2*2 matrix with all zeros except the main diagonal that will be with your values, and Matlab will read it as 2 different groups. Then you change the Xdata of the 'dummy' bars (which you don't see but take some space on the x axis to nan so Matlab will ignore it.

k = [2 5];
b = bar(diag(k));
set(b,{'XData'},{[1 nan],[nan 1]}); % remove the group you don't want
set(gca,{'xticklabel','XTick'},{{'ONE','TWO'},[0.85 1.15]});
b(2).FaceColor = 'r'; % choose a different color

The result:

enter image description here

And if you want to generalize this to more groups (here it's 5):

k = 1:5;
data = diag(k);
xdata = eye(numel(k))./eye(numel(k)); % a martix of nan with 1 on the main diagonal
b = bar(diag(k));
% remove all data except one bin in all groups:
set(b,{'XData'},mat2cell(xdata,ones(size(data,1),1),size(data,2)))
X = xlim; 5 get x-axis limits
w = (1-X(1))/(numel(k)/2); % calculate the width of one bin
set(gca,'XTick',X(1)+w/2:w:X(2)) % set the X ticks to the center of the bins
set(gca,'xticklabel',{'ONE','TWO','THREE','FOUR','FIVE'}); % set the labels
set(b,{'FaceColor'},mat2cell(lines(numel(k)),ones(size(data,1),1),3)); % set the colors

and you get:

enter image description here

And finally, if you want them to 'hover' a little above the x-axis, you can add the following lines:

b(1).BaseLine.Color = 'none'; % remove the base line
ylim([-0.1 max(k(:))]) % shift the bars up a little

and get:

enter image description here