Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display labels above a histogram bin?

I have an array a(30,2) where the first column is a unique sample number and the second column is a value assigned to the sample. I plot a histogram of the 2nd column:

hist(a(:,2))

I have N bins and the y-axis tells me how many samples have a value of x, but no information about which samples are in which bin.

How do I plot, above each bin, a list of samples (the number from the first column of my array a) that fall into each bin?

like image 433
RobertD Avatar asked Jan 11 '11 12:01

RobertD


1 Answers

As was shown by both @Jonas and @Itamar Katz, the idea is to use HISTC to get the bin indices that each sample belongs to, then use BAR to plot the result (note that we use the 'histc' mode of display for the BAR function). My answer below is a variation of @Jonas's post:

[EDITED]

%# random data
a = [(1:30)' rand(30,1)];                %'#

%# compute edges (evenly divide range into bins)
nBins = 10;
edges = linspace(min(a(:,2)), max(a(:,2)), nBins+1);

%# compute center of bins (used as x-coord for labels)
bins = ( edges(1:end-1) + edges(2:end) ) / 2;

%# histc
[counts,binIdx] = histc(a(:,2), edges);
counts(end-1) = sum(counts(end-1:end));  %# combine last two bins
counts(end) = [];                        %# 
binIdx(binIdx==nBins+1) = nBins;         %# also fix the last bin index

%# plot histogram
bar(edges(1:end-1), counts, 'histc')
%#bar(bins, counts, 'hist')              %# same thing
ylabel('Count'), xlabel('Bins')

%# format the axis
set(gca, 'FontSize',9, ...
    'XLim',[edges(1) edges(end)], ...    %# set x-limit to edges
    'YLim',[0 2*max(counts)], ...        %# expand ylimit to accommodate labels
    'XTick',edges, ...                   %# set xticks  on the bin edges
    'XTickLabel',num2str(edges','%.2f')) %'# round to 2-digits

%# add the labels, vertically aligned on top of the bars
hTxt = zeros(nBins,1);                   %# store the handles
for b=1:nBins
    hTxt(b) = text(bins(b), counts(b)+0.25, num2str(a(b==binIdx,1)), ...
        'FontWeight','bold', 'FontSize',8, 'EdgeColor','red', ...
        'VerticalAlignment','bottom', 'HorizontalAlignment','center');
end

%# set the y-limit according to the extent of the text
extnt = cell2mat( get(hTxt,'Extent') );
mx = max( extnt(:,2)+extnt(:,4) );       %# bottom+height
ylim([0 mx]);

alt text

If the ticks on the x-axis become too crowded, you can display them rotated with an angle using XTICKLABEL_ROTATE function (submission on FEX).

like image 57
Amro Avatar answered Sep 20 '22 16:09

Amro