Reputation: 610
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
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