Filter matrix rows depending on the values ​​in the second matrix

Given a 2x3 matrix x

and a 4x2 matrix y

, I would like to use each row y

to index into x

. If the value in is x

not equal -1

, I would like to remove this line from y

. Here's an example that does what I would like, except that I would like to do it in a quick, easy way without a loop.

x = [1, 2, 3; -1, 2, -1];
y = [1, 1; 1, 3; 2, 1; 2, 3];

for i=size(y,1):-1:1
   if x(y(i,1), y(i,2)) ~= -1
      y(i,:) = [];
   end
end

      

This leads to:

y =

     2     1
     2     3

      

+1


source to share


3 answers


The original approach to what follows from sub2ind

(used by this rather nice solution posted by Louis) would essentially be as follows:

y = y(x((y(:,2)-1)*size(x,1)+y(:,1))==-1,:)

      


Benchmarking



Benchmarking code

N = 5000;
num_runs = 10000;

x = round(rand(N,N).*2)-1;
y = zeros(N,2);
y(:,1) = randi(size(x,1),N,1);
y(:,2) = randi(size(x,2),N,1);

disp('----------------- With sub2ind ')
tic
for k = 1:num_runs
    y1 = y(x(sub2ind(size(x), y(:,1), y(:,2)))==-1,:);
end
toc,clear y1

disp('----------- With raw version of sub2ind ')
tic
for k = 1:num_runs
    y2 = y(x((y(:,2)-1)*size(x,1)+y(:,1))==-1,:);
end
toc

      

results

----------------- With sub2ind 
Elapsed time is 4.095730 seconds.
----------- With raw version of sub2ind 
Elapsed time is 2.405532 seconds.

      

+3


source


It can be easily vectorized like this (see sub2ind

):



y = y(x(sub2ind(size(x), y(:,1), y(:,2)))==-1,:);

      

+2


source


>> x = [1, 2, 3; -1, 2, -1];
>>y = [1, 1; 
    1, 2; 
    1, 3; 
    2, 1;
    2, 2;
    2, 3];
>>row_idx = reshape((x == -1)',1,6);
>>y = y(row_idx,:);

      

I think you haven't included the entire x index in y. I have included them all in y. Look ..

Generalized version:

>> x = [1, 2, 3; -1, 2, -1];
>>y = [1, 1; 
    1, 2; 
    1, 3; 
    2, 1;
    2, 2;
    2, 3];
>>row_idx = reshape((x == -1)',1,size(x,1)*size(x,2));
>>y = y(row_idx,:);

      

0


source







All Articles