Faster way to create a matrix of the unique() of each row of a matrix

4 views (last 30 days)
Let A be a matrix of relatively big size(A,1), say 2000, and relatively small size(A,2), say 20. I am looking for a faster way to construct a matrix B such that the i-th row of B consists of unique(B(i,:)), padded appropriately, say with 0-s, so that all these rows have the same length (in order to fit together as the matrix B).
I am currently using the following code:
[n,m] = size(A); % A is, say, a non-zero uint8 matrix
A = A.'; % it's better to work with columns in MATLAB?
B = zeros(m,n,'uint8');
t = 0; % will truncate B at t;
for i=1:n % loop through the columns of A.'
col = unique(A(:,i));
s = length(col);
B(1:s,i) = col;
t = max(t,s);
end
B = B.'; % go back to the original form
B = B(:,1:t);
When size(A,1) is big, the long loop is perhaps suboptimal. Moreover, A and B are actually GPU arrays, so the code is supposed to run on the GPU. So is there perhaps a faster/smarter (vectorized) way to do this?
  1 Comment
Marin Genov
Marin Genov on 7 Aug 2022
@Bruno Luong: Yes, you are absolutely right, I was hasty, s was meant to be the length of the vector of unique values. I fixed the code in the original post. Thanks!

Sign in to comment.

Accepted Answer

Bruno Luong
Bruno Luong on 7 Aug 2022
Edited: Bruno Luong on 7 Aug 2022
% Test example
A=randi(4,10,5)
A = 10×5
1 3 1 4 3 2 1 1 1 4 2 1 3 3 3 3 4 4 3 3 1 2 2 3 1 2 2 1 3 3 1 3 1 3 4 4 2 4 2 4 3 1 4 4 3 3 2 4 1 2
[m,n] = size(A);
As=sort(A,2);
b=[true(m,1),diff(As,1,2)>0];
R=repmat((1:m)',1,n);
C=cumsum(b,2);
r=R(b);
c=C(b);
a=As(b);
B=accumarray([r,c],a)
B = 10×4
1 3 4 0 1 2 4 0 1 2 3 0 3 4 0 0 1 2 3 0 1 2 3 0 1 3 4 0 2 4 0 0 1 3 4 0 1 2 3 4
  2 Comments
Bruno Luong
Bruno Luong on 8 Aug 2022
% Test example
A small modification to easier find r
A=randi(4,10,5)
A = 10×5
1 3 1 2 2 1 1 3 2 1 4 1 3 2 4 1 3 1 1 4 1 4 2 4 2 3 3 2 1 2 1 4 2 1 4 1 4 3 4 2 3 2 3 4 2 2 1 2 4 3
[m,n] = size(A);
As=sort(A,2);
b=[true(m,1),diff(As,1,2)>0];
C=cumsum(b,2);
[r,~] = find(b); % not need R
c=C(b);
a=As(b);
B=accumarray([r,c],a)
B = 10×4
1 2 3 0 1 2 3 0 1 2 3 4 1 3 4 0 1 2 4 0 1 2 3 0 1 2 4 0 1 2 3 4 2 3 4 0 1 2 3 4

Sign in to comment.

More Answers (0)

Categories

Find more on Operating on Diagonal Matrices in Help Center and File Exchange

Products


Release

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!