Star
Star

Reputation: 2299

Finding equal rows in Matlab

I have a matrix suppX in Matlab with size GxN and a matrix A with size MxN. I would like your help to construct a matrix Xresponse with size GxM with Xresponse(g,m)=1 if the row A(m,:) is equal to the row suppX(g,:) and zero otherwise.

Let me explain better with an example.

suppX=[1 2 3 4; 
       5 6 7 8; 
       9 10 11 12]; %GxN

A=[1 2 3 4; 
   1 2 3 4; 
   9 10 11 12; 
   1 2 3 4]; %MxN

Xresponse=[1 1 0 1; 
           0 0 0 0;
           0 0 1 0]; %GxM

I have written a code that does what I want.

Xresponsemy=zeros(size(suppX,1), size(A,1));
for x=1:size(suppX,1)
    Xresponsemy(x,:)=ismember(A, suppX(x,:), 'rows').'; 
end

My code uses a loop. I would like to avoid this because in my real case this piece of code is part of another big loop. Do you have suggestions without looping?

Upvotes: 3

Views: 128

Answers (2)

Luis Mendo
Luis Mendo

Reputation: 112769

Here's an alternative to @rayryeng's answer: reduce each row of the two matrices to a unique identifier using the third output of unique with the 'rows' input flag, and then compare the identifiers with singleton expansion (broadcast) using bsxfun:

[~, ~, w] = unique([A; suppX], 'rows');
Xresponse = bsxfun(@eq, w(1:size(A,1)).', w(size(A,1)+1:end));

Upvotes: 2

rayryeng
rayryeng

Reputation: 104555

One way to do this would be to treat each matrix as vectors in N dimensional space and you can find the L2 norm (or the Euclidean distance) of each vector. After, check if the distance is 0. If it is, then you have a match. Specifically, you can create a matrix such that element (i,j) in this matrix calculates the distance between row i in one matrix to row j in the other matrix.

You can treat your problem by modifying the distance matrix that results from this problem such that 1 means the two vectors completely similar and 0 otherwise.

This post should be of interest: Efficiently compute pairwise squared Euclidean distance in Matlab.

I would specifically look at the answer by Shai Bagon that uses matrix multiplication and broadcasting. You would then modify it so that you find distances that would be equal to 0:

nA = sum(A.^2, 2); % norm of A's elements
nB = sum(suppX.^2, 2); % norm of B's elements
Xresponse = bsxfun(@plus, nB, nA.') - 2 * suppX * A.';
Xresponse = Xresponse == 0;

We get:

Xresponse =

  3×4 logical array

   1   1   0   1
   0   0   0   0
   0   0   1   0

Note on floating-point efficiency

Because you are using ismember in your implementation, it's implicit to me that you expect all values to be integer. In this case, you can very much compare directly with the zero distance without loss of accuracy. If you intend to move to floating-point, you should always compare with some small threshold instead of 0, like Xresponse = Xresponse <= 1e-10; or something to that effect. I don't believe that is needed for your scenario.

Upvotes: 3

Related Questions