【问题标题】:Filter matrix rows depending on values in a second matrix根据第二个矩阵中的值过滤矩阵行
【发布时间】:2014-08-27 13:36:44
【问题描述】:

给定一个 2x3 矩阵 x 和一个 4x2 矩阵 y,我想使用 y 的每一行来索引到 x。如果x 中的值不等于-1,我想从y 中删除该行。这是一个可以做我想做的事情的例子,除了我想以一种快速、简单的方式来做,没有循环。

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

这会导致:

y =

     2     1
     2     3

【问题讨论】:

    标签: matlab


    【解决方案1】:

    sub2ind 遵循的原始方法(由 Luis 发布的这个漂亮的 solution 使用)本质上就是这样 -

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

    基准测试

    基准代码

    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
    

    结果

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

    【讨论】:

    • +1 干得好!有一段时间我不知道sub2ind,我会这样做。然后我发现了这个功能并变得懒惰:-)
    • @LuisMendo 哈哈你怎么可能不知道sub2ind! :) 好吧,我想当我们想要避免函数调用以提高性能并依赖基本的数学运算时,这很有趣,让我们的大脑保持运转:) 你已经 +1 了!
    • 一开始我不知道sub2ind,甚至不知道线性索引。我认为线性索引是一些 Matlab 的错误! (“Matlab 如何允许使用 one 索引对 2D 数组进行索引?”)然后我得到了它的逻辑并开始使用它,但是按照您的答案手动进行转换
    • @LuisMendo 哇!您在相当快的时间内已经取得了长足的进步!了解特定语言的工具肯定会有所帮助,但这一切都始于制定非特定语言的解决方案。顺便说一句,一切顺利! :)
    【解决方案2】:

    这可以很容易地向量化如下(参见sub2ind):

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

    【讨论】:

      【解决方案3】:
      >> 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,:);
      

      我认为您没有在 y 中包含 x 的所有索引。我将所有这些都包括在 y 中。看看吧。。

      通用版:

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

      【讨论】:

      • 谢谢@lakesh,遗漏一些索引是故意的。我应该在问题中提到这一点,抱歉。
      • 如果您可以制作一个通用版本,我很乐意将其纳入基准测试。
      • 我无法为这些输入运行 - N = 5, x = round(rand(N,N).*2)-1, y = randi(size(x,1),N,2)
      猜你喜欢
      • 2014-04-05
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多