funklute
funklute

Reputation: 610

find array elements that match one of multiple conditions, sorted by condition matched

I have an m-by-n matrix (n > 3) where the two first columns have a lot of repetition of values. I have another two vectors, call them uniqueCol1 and uniqueCol2, which contain all the possible values for the two columns.

I want to find all the sub-matrices, which will be p-by-n (p =< m), where the two first columns match given values in uniqueCol1 and uniqueCol2. There is up to length(uniqueCol1) * length(uniqueCol2) such sub-matrices.

I could use ismember() to help find these sub-matrices, but I can't see a way of doing this where I would know what parts of the output matched what condition.

Alternatively I can do a for loop, as shown below, but this is extremely slow. Is there a way of vectorizing the below? I imagine the solution would have as output a cell array of these sub-matrices, as each sub-matrix is not generally the same size (so a multi-dimensional array would not work).

myBigMatrix = round(wgn(1000,6,1) * 3);
uniqueCol1 = unique(myBigMatrix(:,1));
uniqueCol2 = unique(myBigMatrix(:,2));
for i = 1:length(uniqueCol1)
    for j = 1:length(uniqueCol2)
        mySubMatrix = myBigMatrix( ...
            myBigMatrix(:,1) == uniqueCol1(i) & ...
            myBigMatrix(:,2) == uniqueCol2(j) , :);
        % then do something with mySubMatrix, 
        % as it's clear from i and j what condition it matched
    end
end

Upvotes: 1

Views: 160

Answers (1)

Luis Mendo
Luis Mendo

Reputation: 112659

You can use the powerful accumarray function for this task:

[uniqueCol1, ~, u1] = unique(myBigMatrix(:,1));
[uniqueCol2, ~, u2] = unique(myBigMatrix(:,2));
R = accumarray([u1 u2], (1:size(myBigMatrix,1)).', [], @(x) {myBigMatrix(sort(x),:)})

Then R{m,n} contains the submatrix that matches the m-th element of uniqueCol1 and the n-th element of uniqueCol2.

Example:

myBigMatrix =
     3     5     3
     3     2     2
     3     5     1
     3     2     1
     1     5     4
     4     3     4

gives

>> uniqueCol1.'
ans =
     1     3     4
>> uniqueCol2.'
ans =
     2     3     5

>> R
R = 
              []              []    [1x3 double]
    [2x3 double]              []    [2x3 double]
              []    [1x3 double]              []

>> R{2,1} %// submatrix corresponding to 3 in first col and 2 in second col
ans =
     3     2     2
     3     2     1

>> R{3,2} %// submatrix corresponding to 4 in first col and 3 in second col
ans =
     4     3     4

Upvotes: 2

Related Questions