我在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.
我想要的例子:
结果中的A-B表示从A中删除B行。与A-C相同。
答案 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)
使用bsxfun:
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
来比较A
和B
的第一列与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 permute
到one permute
-
A(~any(all(bsxfun(@eq,A(:,1:2),permute(B(:,1:2),[3 2 1])),2),3),:)