2

I have the following range from a much larger matrix :

range(a)

ans =

94   153   144    59    79    90   131    64

My professor is asking us to: Divide the range into N = 10 equal-length segments (hereafter called “bins”), and for each bin, find its bounds (aj, bj) as well as its center cj.

(5) Place each measured bacterial count xi into that bin whose lower bound is less than or equal to xi and whose upper bound is greater than xi; thereafter, for each bin count the number of xi assigned to it (= nj).

(6) Plot a histogram of the measured bacterial counts using N = 10 bars. Try the MATLAB functions hist(x,N) and bar(c, n)

I know this is a lot, but I have absolutely no instruction from this guy and would really appreciate a helping hand :)

Dennis Jaheruddin
  • 21,208
  • 8
  • 66
  • 122
patrick.belon
  • 65
  • 2
  • 3
  • 7
  • See this answer & video: http://stackoverflow.com/questions/7013913/matlab-transform-continuous-data-to-discrete-data/7014168#7014168 – Iterator Oct 27 '11 at 04:40
  • you also could check out the answers in this question: http://stackoverflow.com/questions/4657719/how-to-display-labels-above-a-histogram-bin – Amro Oct 27 '11 at 07:18

2 Answers2

8

Consider the following example, it should solve all your points:

%# random data vector of integers
M = randi([50 200], [100 1]);

%# compute bins
nbins = 10;
binEdges = linspace(min(M),max(M),nbins+1);
aj = binEdges(1:end-1);     %# bins lower edge
bj = binEdges(2:end);       %# bins upper edge
cj = ( aj + bj ) ./ 2;      %# bins center

%# assign values to bins
[~,binIdx] = histc(M, [binEdges(1:end-1) Inf]);

%# count number of values in each bin
nj = accumarray(binIdx, 1, [nbins 1], @sum);

%# plot histogram
bar(cj,nj,'hist')
set(gca, 'XTick',binEdges, 'XLim',[binEdges(1) binEdges(end)])
xlabel('Bins'), ylabel('Counts'), title('histogram of measured bacterial')

Note that this correctly handles the last bin (read this related question for a discussion on those edge cases)

screenshot

Community
  • 1
  • 1
Amro
  • 123,847
  • 25
  • 243
  • 454
  • It gives me an error that says: ??? Error using ==> accumarray Third input SZ must be a full row vector with one element for each column of SUBS. Error in ==> EE300Project1 at 29 nj = accumarray(binIdx, 1, [nbins ], @sum); – patrick.belon Oct 29 '11 at 20:45
  • @patrick.belon: it looks to me you are missing a `1` in there: `nj = accumarray(binIdx, 1, [nbins 1], @sum);`. This also can be simplified as just: `nj = accumarray(binIdx, 1);` – Amro Oct 30 '11 at 02:16
  • @patrick.belon: you should edit your question and post the code you are using. I suspect you are doing something wrong as my example above works just fine... – Amro Oct 31 '11 at 23:10
  • @Amro, thanks for the examples. it seems to be that the code only works for positive integer numbers, right? what if we have in our data `0's` (i.e. `min(M)==0`)? – Tin Jul 28 '14 at 15:46
  • @Tin: no, it should work for any a vector of numbers (positive/negative, integers/floats). A `0` value in the vector isn't treated any differently.. – Amro Jul 28 '14 at 18:00
  • @Amro, I fixed the problem: `[~, bin_idx] = histc( X, [-Inf,bin_centers(1:end-1), Inf] );`, note that I added `-Inf` – Tin Jul 29 '14 at 10:15
  • @Tin: well that's not the same thing, you are using **bin centers** while `histc` expects **bin edges** (read [the docs](http://www.mathworks.com/help/matlab/ref/histc.html))... The ranges specified by the edges are in the form `[lower,upper)` (lower bound inclusive). I used the centers only for plotting purposes (`bar` function call)... Read my code again :) – Amro Jul 29 '14 at 18:08
  • ok thanks. @Demetris you can do this `nj = accumarray(binIdx(:), 1, [nbins 1]);` to handle both row/column vectors as input. – Amro Mar 02 '16 at 23:37
3

computing histogram:

range = [94   153   144    59    79    90   131    64]
[n,xout] = hist(range, 10)

xout is bin centers, n bin counts.

plotting bar graph:

 bar(xout,n)

computing bin edges:

width = xout(2)-xout(1)
xoutmin = xout-width/2
xoutmax = xout+width/2
Tal Darom
  • 1,379
  • 1
  • 8
  • 26