当前位置:  开发笔记 > 编程语言 > 正文

在MATLAB中从矩阵中删除元素的最有效/优雅的方法是什么?

如何解决《在MATLAB中从矩阵中删除元素的最有效/优雅的方法是什么?》经验,为你挑选了3个好方法。

我想从矩阵中删除几个特定值(如果存在).极有可能在矩阵中存在多个值的副本.

例如,考虑N乘2矩阵intersections.如果值对[a b][c d]在该矩阵中作为行存在,我想删除它们.

比方说,我想删除像行[-2.0 0.5][7 7]下面的矩阵:

intersections =

   -4.0000    0.5000
   -2.0000    0.5000
    2.0000    3.0000
    4.0000    0.5000
   -2.0000    0.5000

所以删除后我得到:

intersections = 

   -4.0000    0.5000
    2.0000    3.0000
    4.0000    0.5000

这样做最有效/优雅的方法是什么?



1> gnovice..:

试试这个单行(其中A是你的交集矩阵,B是要删除的值):

A = [-4.0 0.5;
     -2.0 0.5;
      2.0 3.0;
      4.0 0.5;
     -2.0 0.5];
B = [-2.0 0.5];
A = A(~all(A == repmat(B,size(A,1),1),2),:);

然后只需为要删除的每个新B重复最后一行.

编辑:

......这是另一种选择:

A = A((A(:,1) ~= B(1)) | (A(:,2) ~= B(2)),:);

警告:此处的答案最适用于不期望小浮点错误的情况(即使用整数值).如本后续问题所述,使用"=="和"〜="运算符可能会导致不必要的结果.在这种情况下,应修改上述选项以使用关系运算符而不是相等运算符.例如,我添加的第二个选项将更改为:

tolerance = 0.001;   % Or whatever limit you want to set
A = A((abs(A(:,1)-B(1)) > tolerance) | (abs(A(:,2)-B(2)) > tolerance),:);

只是一个快速的头!=)


一些RUDIMENTARY时间:

如果有人真的对效率感兴趣,我只是通过三种不同的方式来获得矩阵的子索引(我上面列出的两个选项和Fanfan的 STRMATCH选项):

>> % Timing for option #1 indexing:
>> tic; for i=1:10000, index = ~all(A == repmat(B,size(A,1),1),2); end; toc;
Elapsed time is 0.262648 seconds.
>> % Timing for option #2 indexing:
>> tic; for i=1:10000, index = (A(:,1) ~= B(1)) | (A(:,2) ~= B(2)); end; toc;
Elapsed time is 0.100858 seconds.
>> % Timing for STRMATCH indexing:
>> tic; for i=1:10000, index = strmatch(B,A); end; toc;
Elapsed time is 0.192306 seconds.

正如您所看到的,STRMATCH选项比我的第一个建议更快,但我的第二个建议是所有三个中最快的.但请注意,我的选项和Fanfan的做法略有不同:我的选项返回要保留的行的逻辑索引,而Fanfan返回要删除的行的线性索引.这就是STRMATCH选项使用表单的原因:

A(index,:) = [];

而我的使用形式:

A = A(index,:);

但是,我的索引可以否定使用第一种形式(索引要删除的行):

A(all(A == repmat(B,size(A,1),1),2),:) = [];    % For option #1
A((A(:,1) == B(1)) & (A(:,2) == B(2)),:) = [];  % For option #2



2> 小智..:

这里的简单解决方案是设置成员函数,即setdiff,union和ismember.

A = [-4  0.5;
   -2    0.5;
    2    3;
    4    0.5;
   -2    0.5];

B = [-2 .5;7 7];

查看成员对两个数组的作用.使用'rows'选项.

ismember(A,B,'rows')

ans =
     0
     1
     0
     0
     1

由于我们希望删除也在B中的A行,只需执行以下操作:

A(ismember(A,B,'rows'),:) = []

A = 
      -4          0.5
       2            3
       4          0.5

请注意,集合成员函数会查找完全匹配.等于1/2的整数或1/2的倍数满足该要求.它们在MATLAB中用浮点运算表示.

如果这些数字是真正的浮点数,我会更加小心.在那里,我已经对差异使用了容忍度.在那种情况下,我可能已经计算了两组数字之间的点间距离矩阵,只有当它落在B行之一的某个给定距离内时才删除A行.



3> 小智..:

您还可以滥用strmatch函数来满足您的需要:以下代码删除矩阵A中给定行b的所有出现

A(strmatch(b, A),:) = [];

如果需要删除多行,例如矩阵B中的所有行,则迭代它们:

for b = B'
   A(strmatch(b, A),:) = [];
end

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有