Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to quickly get the array of multiplicities

What is the fastest way of taking an array A and outputing both unique(A) [i.e. the set of unique array elements of A] as well as the multiplicity array which takes in its i-th place the i-th multiplicity of the i-th entry of unique(A) in A.

That's a mouthful, so here's an example. Given A=[1 1 3 1 4 5 3], I want:

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

This can be done with a tedious for loop, but would like to know if there is a way to exploit the array nature of MATLAB.

like image 914
Lepidopterist Avatar asked Feb 11 '14 19:02

Lepidopterist


3 Answers

uA = unique(A);
mult = histc(A,uA);

Alternatively:

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.
like image 192
Luis Mendo Avatar answered Nov 11 '22 06:11

Luis Mendo


[uA,~,ic] = unique(A);    % uA(ic) == A
mult = accumarray(ic.',1);

accumarray is very fast. Unfortunately, unique gets slow with 3 outputs.


Late addition:

uA = unique(A);
mult = nonzeros(accumarray(A(:),1,[],@sum,0,true))
like image 34
chappjc Avatar answered Nov 11 '22 05:11

chappjc


S = sparse(A,1,1);
[uA,~,mult] = find(S);

I've found this elegant solution in an old Newsgroup thread.

Testing with the benchmark of Luis Mendo 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 results in Error: Maximum variable size allowed by the program is exceeded.)

like image 2
bbrrck Avatar answered Nov 11 '22 06:11

bbrrck