74

Does anyone know how to count the number of times a value appears in a matrix?

For example, if I have a 1500 x 1 matrix M (vector) which stores the values of weekdays (1 - 7), how could I count how many Sundays (1), Mondays(2), ... , Saturdays(7) are stored in M?

gnovice
  • 125,304
  • 15
  • 256
  • 359
Niko Gamulin
  • 66,025
  • 95
  • 221
  • 286

7 Answers7

100

Have a look at Determine and count unique values of an array.

Or, to count the number of occurrences of 5, simply do

sum(your_matrix == 5)
aioobe
  • 413,195
  • 112
  • 811
  • 826
73

Here's a list of all the ways I could think of to counting unique elements:

M = randi([1 7], [1500 1]);

Option 1: tabulate

t = tabulate(M);
counts1 = t(t(:,2)~=0, 2);

Option 2: hist/histc

counts2_1 = hist( M, numel(unique(M)) );
counts2_2 = histc( M, unique(M) );

Option 3: accumarray

counts3 = accumarray(M, ones(size(M)), [], @sum);
%# or simply: accumarray(M, 1);

Option 4: sort/diff

[MM idx] = unique( sort(M) );
counts4 = diff([0;idx]);

Option 5: arrayfun

counts5 = arrayfun( @(x)sum(M==x), unique(M) );

Option 6: bsxfun

counts6 = sum( bsxfun(@eq, M, unique(M)') )';

Option 7: sparse

counts7 = full(sparse(M,1,1));
Amro
  • 123,847
  • 25
  • 243
  • 454
  • 4
    I prefer this answer to the one that links to mathworks since it is very clear and self-contained. – gakera Apr 28 '14 at 14:26
  • @Amro With `M = [1 2 100000]`, option 2, `counts2_1 = hist( M, numel(unique(M)) )` gives `[2 0 1]` which is not good enough, yeah? It should be just `counts2_1 = hist( M, unique(M) )`. – Evgeni Sergeev Aug 09 '14 at 04:29
  • @EvgeniSergeev: You're right. The second argument of [HIST](http://www.mathworks.com/help/matlab/ref/hist.html#inputarg_xvalues) can have different meanings: 1) it can be a scalar denoting the number of bins `hist(data,nbins)` (in which case the range `[min(data),max(data)]` is divided into equal-sized `N`-bins) 2) it can also specify the bin centers as `hist(data,xvalues)`, assuming `xvalues` is a vector of evenly-spaced values 3) or in case the vector `xvalues` is not evenly-spaced, then the midpoints between consecutive values are used as bin edges. – Amro Aug 09 '14 at 14:46
  • @EvgeniSergeev: In all three cases the code in `hist` internally ends up calling the `histc` function (check the source code `edit hist.m`, whereas `histc` is a built-in function). So I think it is best to avoid `hist` here and directly call `histc` with explicit bin edges as I've showed above. – Amro Aug 09 '14 at 14:47
  • 1
    The examples I gave above were mostly intended for the data shown by OP, and some of the methods assume data values are *integers* and preferably start at `1`. See the following answers on how to handle more cases in general: http://stackoverflow.com/a/4093228/97160, http://stackoverflow.com/a/6933863/97160 – Amro Aug 09 '14 at 15:14
10

One way you can perform this operation for all the values 1 through 7 at once is to use the function ACCUMARRAY:

>> M = randi(7,1500,1);  %# Some random sample data with the values 1 through 7
>> dayCounts = accumarray(M,1)  %# Will return a 7-by-1 vector

dayCounts =

   218       %# Number of Sundays
   200       %# Number of Mondays
   213       %# Number of Tuesdays
   220       %# Number of Wednesdays
   234       %# Number of Thursdays
   219       %# Number of Fridays
   196       %# Number of Saturdays
gnovice
  • 125,304
  • 15
  • 256
  • 359
5

assume w contains week numbers ([1:7])

n = histc(M,w)

if you do not know the range of numbers in M:

n = histc(M,unique(M))

It is such as a SQL Group by command!

Babak
  • 101
  • 1
  • 5
4

this would be perfect cause we are doing operation on matrix, and the answer should be a single number

sum(sum(matrix==value))
jbr
  • 6,198
  • 3
  • 30
  • 42
radhe_shyam
  • 159
  • 1
  • 5
3

This is a very good function file available on Matlab Central File Exchange.

countmember.m link

This function file is totally vectorized and hence very quick. Plus, in comparison to the function being referred to in aioobe's answer, this function doesn't use the accumarray function, which is why this is even compatible with older versions of Matlab. Also, it works for cell arrays as well as numeric arrays.

SOLUTION : You can use this function in conjunction with the built in matlab function, "unique".

occurance_count = countmember(unique(M),M)

occurance_count will be a numeric array with the same size as that of unique(M) and the different values of occurance_count array will correspond to the count of corresponding values (same index) in unique(M).

Abhinav
  • 1,882
  • 1
  • 18
  • 34
2

Use nnz instead of sum. No need for the double call to collapse matrices to vectors and it is likely faster than sum.

nnz(your_matrix == 5)

Doc

Andy Campbell
  • 2,177
  • 13
  • 15