Reputation: 323
I am stuck with a bar plot in Matlab. I got it to work with Matlab help and this this forum until here, but on the x-axis, there are still only 2 names. I would like to have the "names" under the bars and the "categories" where the 2 names show up now. Thank you!
values = [4 10...
11 2 3;...
4 1...
5 2 -10];
names = {'PreSplitTotalEON' 'PostSplitTotalEON'...
'PreSplitPureEON' 'PostSplitPureEON' 'PostSplitUniper';...
'PreSplitTotalRWE' 'PostSplitTotalRWE'...
'PreSplitPureRWE' 'PostSplitPureRWE' 'PostSplitInnogy'};
categories = {'EON', 'RWE'};
b = bar(values,'FaceColor','flat');
xticklabels([names(1,:)';names(2,:)'])
% This will set labels to be used for each tick of the x-axis
xticks(1:1:length([names(1,:)';names(2,:)']))
% This will set how many ticks you want on the x-axis. Here, there
% should be 48 ticks being generated. One for each piece of data you have.
xtickangle(90)
% This will rotate the label so that the labels will not overlap
% with one another. This is in degrees.
for k = 1:size(values,2) % for fancier colors.
b(k).CData = k;
end
Upvotes: 0
Views: 681
Reputation: 81
The default way would be to use legend
to display the name of each element in the group. But the position of each bar can be accessed through the XOffset
and XData
properties. See this answer in matlab central.
So you can use something like:
ticksList = b(1).XData+arrayfun(@(x)x.XOffset, b)';
xticks(ticksList(:))
xticklabels([names(1,:)';names(2,:)'])
to correctly display the names below each bar. However, I don't see how you want to display the names of each bar and the categories together below the bars without overlapping. You could instead display the categories on top by creating a new axes. Adding Something like:
ax1 = gca;
ax2 = axes('Position', get(ax1, 'Position'),'Color', 'none');
set(ax2, 'XAxisLocation', 'top','YAxisLocation','Right');
set(ax2, 'XLim', get(ax1, 'XLim'),'YLim', get(ax1, 'YLim'));
xticks(b(1).XData)
xticklabels(categories)
I.e. the complete code would be now:
clear all
close all
values = [4 1 11 2 3; 4 1 5 2 -10];
names = {'Pre split total EON' 'Post split total EON'...
'Pre split pure EON' 'Post split pure EON' 'Post split Uniper';...
'Pre split total RWE' 'Post split total RWE'...
'Pre split pure RWE' 'Post split pure RWE' 'PostSplitInnogy'};
categories = {'EON','RWE'};
figure;
b = bar(values,'FaceColor','flat');
ticksList = b(1).XData+arrayfun(@(x)x.XOffset, b)';
xticks(ticksList(:))
xticklabels([names(1,:)';names(2,:)'])
xtickangle(90)
ax1 = gca;
ax2 = axes('Position', get(ax1, 'Position'),'Color', 'none');
set(ax2, 'XAxisLocation', 'top','YAxisLocation','Right');
set(ax2, 'XLim', get(ax1, 'XLim'),'YLim', get(ax1, 'YLim'));
set(ax2, 'YTick', []);
xticks(b(1).XData)
xticklabels(categories)
for k = 1:size(values,2) % for fancier colors.
b(k).CData = k;
end
Upvotes: 2
Reputation: 10440
Here is a fix for your code to get the desired output (explenations inside):
values = [4 10 11 2 3;
4 1 5 2 -10];
names = {'PreSplitTotal' 'PostSplitTotal'...
'PreSplitPure' 'PostSplitPure' 'PostSplitUniper';...
'PreSplitTotal' 'PostSplitTotal'...
'PreSplitPure' 'PostSplitPure' 'PostSplitInnogy'}.'; % <-- note the transpose!
categories = {'EON', 'RWE'};
N_names = size(values,2);
ax = axes('NextPlot','add'); % <-- same as 'hold on'
col = lines(N_names); % choose your favorite colormap
% draw the bars in pairs by their 'names':
for k = 1:N_names % for fancier colors.categories
b = bar(ax,[k k+N_names+1],values(:,k),0.15,...
'FaceColor',col(k,:));
end
xticks([1:N_names (N_names+2:N_names*2+1)]) % does not crate a tick for the space between categories
xticklabels(names(:))
xtickangle(30)
% place the category name on top of the axes:
text(ceil(N_names/2)+[0 N_names+1],ax.YLim(2).*[1 1],categories,...
'VerticalAlignment','bottom','HorizontalAlignment','center')
Upvotes: 1
Reputation: 364
The required code to do so is given below.
close all
clear all
values = [4 10 ...
11 2 3; ...
4 1 ...
5 2 -10];
% just declare the names lables as a simple 1-D cell array
% remove the columns and construct as row wise cell array
names = {'PreSplitTotalEON','PostSplitTotalEON', ...
'PreSplitPureEON', 'PostSplitPureEON', 'PostSplitUniper', ...
'PreSplitTotalRWE', 'PostSplitTotalRWE', ...
'PreSplitPureRWE', 'PostSplitPureRWE', 'PostSplitInnogy'};
% declare the categories label
categories = {'EON', 'RWE'};
% construct the bar
b = bar(values,'FaceColor','flat');
%-> mark the respective xticks <-
% on close inspepection, it was found that the bars starts
% near 0.54 and end at nearly 2.31 at the x-axis
% so divide the x axis in 12 ticks within those limits.
xticks([linspace(0.54, 2.31, 12)]);
% now put the lables at those limits, that all
xticklabels({categories{1}, names{1:5}, categories{2}, names{6:10}})
xtickangle(90)
% This will rotate the label so that the labels will not overlap
% with one another. This is in degrees.
for k = 1:5 % for fancier colors.
b(k).CData = k;
end
Upvotes: 1