I have two matrices in Matlab A and B, which have equal number of columns but different number of rows. The number of rows in B is also less than the number of rows in A. B is actually a subset of A.
How can I remove those rows efficiently from A, where the values in columns 1 and 2 of A are equal to the values in columns 1 and 2 of matrix B?
At the moment I'm doing this:
for k = 1:size(B, 1)
A(find((A(:,1) == B(k,1) & A(:,2) == B(k,2))), :) = [];
end
and Matlab complains that this is inefficient and that I should try to use any
, but I'm not sure how to do it with any
. Can someone help me out with this? =)
I tried this, but it doesn't work:
A(any(A(:,1) == B(:,1) & A(:,2) == B(:,2), 2), :) = [];
It complains the following:
Error using ==
Matrix dimensions must agree.
Example of what I want:
A-B in the results means that the rows of B are removed from A. The same goes with A-C.
The easiest way to remove a row or column from a matrix is to set that row or column equal to a pair of empty square brackets [] . For example, create a 4-by-4 matrix and remove the second row.
A matrix with the same number of rows and columns is called a square matrix.
Any 2 columns (or rows) of a matrix can be exchanged. If the ith and jth rows are exchanged, it is shown by Ri ↔ Rj and if the ith and jth columns are exchanged, it is shown by Ci ↔ Cj.
try using setdiff
. for example:
c=setdiff(a,b,'rows')
Note, if order is important use:
c = setdiff(a,b,'rows','stable')
Edit: reading the edited question and the comments to this answer, the specific usage of setdiff
you look for is (as noticed by Shai):
[temp c] = setdiff(a(:,1:2),b(:,1:2),'rows','stable')
c = a(c,:)
you can just use ismember
:
a(~ismember(a(:,1:2),b(:,1:2),'rows'),:)
Use bsxfun:
compare = bsxfun( @eq, permute( A(:,1:2), [1 3 2]), permute( B(:,1:2), [3 1 2] ) );
twoEq = all( compare, 3 );
toRemove = any( twoEq, 2 );
A( toRemove, : ) = [];
First we use bsxfun
to compare all pairs of first to column of A
and B
, resulting with compare
of size numRowsA
-by-numRowsB
-by-2 with true
where compare( ii, jj, kk ) = A(ii,kk) == B(jj,kk)
.
Then we use all
to create twoEq
of size numRowsA
-by-numRowsB
where each entry indicates if both corresponding entries of A
and B
are equal.
Finally, we use any
to select rows of A
that matches at least one row of B
.
By removing rows of A
inside a loop (i.e., A( ... ) = []
) you actually resizing A
at almost each iteration. See this post on why exactly this is a bad practice.
setdiff
In order to use setdiff
(as suggested by natan) on only the first two columns you'll need use it's second output argument:
[ignore, ia] = setdiff( A(:,1:2), B(:,1:2), 'rows', 'stable' );
A = A( ia, : ); % keeping only relevant rows, beyond first two columns.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With