查看单个帖子
旧 2019-12-10, 16:49   #1
poster
高级会员
 
注册日期: 2019-11-21
帖子: 3,006
声望力: 66
poster 正向着好的方向发展
帖子 在MATLAB中从矩阵中删除元素的最有效/最优雅的方法是什么?

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

例如,考虑N×2矩阵intersections 。如果值对[ab]和[cd]作为该矩阵中的行存在,我想删除它们。

假设我要在以下矩阵中删除[-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 什么是最有效/最优雅的方法?


回答:
尝试以下一种方法(其中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),:); 只是快速抬起头! =)

基本时间:

如果有人真的对效率感兴趣,我只是对三种不同的方式做了一些简单的计时,以获取矩阵的子索引(上面列出的两个选项和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

更多&回答...
poster 当前离线   回复时引用此帖