4
votes

I would like to apply the function unique to each row of a given matrix, without involving any for loop. Suppose I have the following 4-by-5 matrix

full(A) = [0    1     0     0    1
           2    1     0     3    0
           1    2     0     0    2
           0    3     1     0    0]

where A is the corresponding sparse matrix. As an example using a for loop, I can do

uniq = cell(4,1);
for i = 1:4
    uniq{i} = unique(A(i,:));
end

and I would obtain the cell structure uniq given by

uniq{1} = {1}
uniq{2} = {[1 2 3]}
uniq{3} = {[1 2]}
uniq{4} = {[1 3]}

Is there a quicker way to vectorize this and avoid for loops? I need to apply this to matrices M-by-5 with M large. Note that I'm not interested in the number of unique elements per row (I know there are around answers for such a problem).

2

2 Answers

4
votes

You can use accumarray with a custom function:

A = sparse([0 1 0 0 1; 2 1 0 3 0; 1 2 0 0 2; 0 3 1 0 0]); % data
[ii, ~, vv] = find(A);
uniq = accumarray(ii(:), vv(:), [], @(x){unique(x.')});

This gives:

>> celldisp(uniq)
uniq{1} =
     1
uniq{2} =
     1     2     3
uniq{3} =
     1     2
uniq{4} =
     1     3
2
votes

you can use num2cell(A,2) to convert each row into cell and then cellfun with unique to get cell array of unique values from each row:

% generate large nX5 matrix
n = 5000;
A = randi(5,n,5);    
% convert each row into cell
C = num2cell(A,2);
% take unique values from each cell
U = cellfun(@unique,C,'UniformOutput',0);