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

5 vues (au cours des 30 derniers jours)
Marin Genov
Marin Genov le 7 Août 2022
Commenté : Marin Genov le 8 Août 2022
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 commentaire
Marin Genov
Marin Genov le 7 Août 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!

Connectez-vous pour commenter.

Réponse acceptée

Bruno Luong
Bruno Luong le 7 Août 2022
Modifié(e) : Bruno Luong le 7 Août 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 commentaires
Bruno Luong
Bruno Luong le 8 Août 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

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Operating on Diagonal Matrices dans Help Center et File Exchange

Produits


Version

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by