Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove those rows of matrix A, which have equal values with matrix B in specified columns in Matlab?

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:

enter image description here

enter image description here

A-B in the results means that the rows of B are removed from A. The same goes with A-C.

like image 849
jjepsuomi Avatar asked Jun 19 '14 06:06

jjepsuomi


People also ask

How do I remove a row from a matrix in Matlab?

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.

What is a matrix with the same number of rows as columns?

A matrix with the same number of rows and columns is called a square matrix.

How do you interchange rows and columns in a 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.


2 Answers

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,:)

Alternative solution:

you can just use ismember:

a(~ismember(a(:,1:2),b(:,1:2),'rows'),:)
like image 147
bla Avatar answered Oct 06 '22 08:10

bla


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, : ) = [];

Explaining the code:

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.

What's wrong with original code:

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.

Using 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.
like image 32
Shai Avatar answered Oct 06 '22 07:10

Shai