How to quickly get an array of multiplicities

What is the fastest way to take an array A and output as unique(A) [i.e. a set of unique elements of the array A ], as well as an array of multiplicity, which occupies in the i-th place the i-th multiplicity of the i-th input of unique(A) in A

This is a sip, here is an example. Given A=[1 1 3 1 4 5 3] , I want:

  • unique(A)=[1 3 4 5]
  • mult = [3 2 1 1]

This can be done with a tedious loop, but I would like to know if there is a way to use the MATLAB array.

+7
arrays matlab unique accumarray
source share
3 answers
 uA = unique(A); mult = histc(A,uA); 

As an alternative:

 uA = unique(A); mult = sum(bsxfun(@eq, uA(:).', A(:))); 

Benchmarking

 N = 100; A = randi(N,1,2*N); %// size 1 x 2*N %// Luis Mendo, first approach tic for iter = 1:1e3; uA = unique(A); mult = histc(A,uA); end toc %// Luis Mendo, second approach tic for iter = 1:1e3; uA = unique(A); mult = sum(bsxfun(@eq, uA(:).', A(:))); end toc %'// chappjc tic for iter = 1:1e3; [uA,~,ic] = unique(A); % uA(ic) == A mult= accumarray(ic.',1); end toc 

Results with N = 100 :

 Elapsed time is 0.096206 seconds. Elapsed time is 0.235686 seconds. Elapsed time is 0.154150 seconds. 

Results with N = 1000 :

 Elapsed time is 0.481456 seconds. Elapsed time is 4.534572 seconds. Elapsed time is 0.550606 seconds. 
+7
source share
 [uA,~,ic] = unique(A); % uA(ic) == A mult = accumarray(ic.',1); 

accumarray very fast. Unfortunately, unique slows down with 3 outputs.


Late addition:

 uA = unique(A); mult = nonzeros(accumarray(A(:),1,[],@sum,0,true)) 
+2
source share
 S = sparse(A,1,1); [uA,~,mult] = find(S); 

I found this elegant solution in the old Newsgroup thread .

Testing with the Luis Mendo test for N = 1000 :

 Elapsed time is 0.228704 seconds. % histc Elapsed time is 1.838388 seconds. % bsxfun Elapsed time is 0.128791 seconds. % sparse 

(On my machine accumarray result is Error: Maximum variable size allowed by the program is exceeded. )

+2
source share

All Articles