如何删除矩阵A的那些行,它们与Matlab中指定列中的矩阵B具有相等的值?

时间:2014-06-19 06:21:47

标签: performance matlab matrix vectorization

我在Matlab A和B中有两个矩阵,它们具有相同的列数但行数不同。 B中的行数也小于A中的行数.B实际上是A的子集。

如何有效地从A中删除这些行,其中A的第1列和第2列中的值等于矩阵B的第1列和第2列中的值?

目前我正在这样做:

for k = 1:size(B, 1)
     A(find((A(:,1) == B(k,1) & A(:,2) == B(k,2))), :) = [];
end

并且Matlab抱怨这是低效的,我应该尝试使用any,但我不确定如何使用any。有人可以帮我解决这个问题吗? =)

我试过这个,但它不起作用:

A(any(A(:,1) == B(:,1) & A(:,2) == B(:,2), 2), :) = [];

它抱怨如下:

Error using  == 
Matrix dimensions must agree.

我想要的例子:

enter image description here

enter image description here

结果中的A-B表示从A中删除B行。与A-C相同。

3 个答案:

答案 0 :(得分:4)

尝试使用setdiff。例如:

c=setdiff(a,b,'rows')

注意,如果订单很重要,请使用:

c = setdiff(a,b,'rows','stable')

修改:阅读已修改的问题以及对此答案的评论,您寻找的setdiff的具体用法是(正如Shai所注意到的):

[temp c] = setdiff(a(:,1:2),b(:,1:2),'rows','stable')
c = a(c,:)

替代解决方案:

您可以使用ismember

a(~ismember(a(:,1:2),b(:,1:2),'rows'),:)

答案 1 :(得分:2)

使用

compare = bsxfun( @eq, permute( A(:,1:2), [1 3 2]), permute( B(:,1:2), [3 1 2] ) );
twoEq = all( compare, 3 );
toRemove = any( twoEq, 2 ); 
A( toRemove, : ) = [];

解释代码:

首先,我们使用bsxfun来比较AB的第一列与compare的所有对,结果为numRowsA,大小为numRowsB - by- { {1}} - by {2 true compare( ii, jj, kk ) = A(ii,kk) == B(jj,kk) 然后,我们使用all创建大小为twoEq的{​​{1}} - 按 - numRowsA,其中每个条目指示{strong>两个对应的{{1}条目}和numRowsB相等 最后,我们使用A选择与B的至少一行匹配的any行。

原始代码有什么问题:

通过删除循环内的A行(即B),您实际上几乎每次迭代都会调整A的大小。请参阅this post,了解为什么这是不良做法

使用setdiff

为了在前两列中使用A( ... ) = [](由natan建议),您需要使用它的第二个输出参数:

A

答案 2 :(得分:2)

这是另一个bsxfun实现 -

A(~any(squeeze(all(bsxfun(@eq,A(:,1:2),permute(B(:,1:2),[3 2 1])),2)),2),:)

另一个危险地接近Shai's solution,但仍然避免two permuteone permute -

A(~any(all(bsxfun(@eq,A(:,1:2),permute(B(:,1:2),[3 2 1])),2),3),:)