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

4 visualizzazioni (ultimi 30 giorni)
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 Commento
Marin Genov
Marin Genov il 7 Ago 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!

Accedi per commentare.

Risposta accettata

Bruno Luong
Bruno Luong il 7 Ago 2022
Modificato: Bruno Luong il 7 Ago 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 Commenti
Bruno Luong
Bruno Luong il 8 Ago 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

Accedi per commentare.

Più risposte (0)

Categorie

Scopri di più su Operating on Diagonal Matrices in Help Center e File Exchange

Prodotti


Release

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by