Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 如何删除矩阵A中与矩阵B在Matlab中指定列中的值相等的行?_Performance_Matlab_Matrix_Vectorization_Bsxfun - Fatal编程技术网

Performance 如何删除矩阵A中与矩阵B在Matlab中指定列中的值相等的行?

Performance 如何删除矩阵A中与矩阵B在Matlab中指定列中的值相等的行?,performance,matlab,matrix,vectorization,bsxfun,Performance,Matlab,Matrix,Vectorization,Bsxfun,我在MatlabA和B中有两个矩阵,它们的列数相等,但行数不同。B中的行数也小于A中的行数。B实际上是A的子集 当A的第1列和第2列中的值等于矩阵B的第1列和第2列中的值时,如何有效地从A中删除这些行 目前我正在这样做: for k = 1:size(B, 1) A(find((A(:,1) == B(k,1) & A(:,2) == B(k,2))), :) = []; end Matlab抱怨这是低效的,我应该尝试使用any,但我不确定如何使用any。有人能帮我解决这个问

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

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

目前我正在这样做:

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表示B行从A中删除。A-C也是如此。

尝试使用。例如:

c=setdiff(a,b,'rows')
注意,如果订单很重要,请使用:

c = setdiff(a,b,'rows','stable')
Edit:阅读编辑后的问题和对此答案的评论,您要查找的
setdiff
的具体用法是(正如Shai所注意到的):

替代解决方案: 您只需使用:

使用:

解释代码: 首先,我们使用
bsxfun
比较
A
B
列的所有对First-to-column,结果是
compare
大小
numRowsA
-by-
numRowsB
-by-2和
true
其中
比较(ii,jj,kk)=A(ii,kk)=B(jj,kk)

然后我们使用
all
创建大小为
numRowsA
-by-
numRowsB
twoEq
,其中每个条目表示
A
B
的对应条目是否相等。
最后,我们使用
any
选择与至少一行
B
匹配的
A

原始代码有什么问题: 通过删除循环中的
A
行(即
A(…)=[]
),实际上可以在几乎每次迭代中调整
A
。请参见为什么这是一种不良做法

使用 为了仅在前两列上使用
setdiff
(如所建议),您需要使用它的第二个输出参数:

[ignore, ia] = setdiff( A(:,1:2), B(:,1:2), 'rows', 'stable' );
A = A( ia, : ); % keeping only relevant rows, beyond first two columns.

下面是另一个
bsxfun
实现-

A(~any(squeeze(all(bsxfun(@eq,A(:,1:2),permute(B(:,1:2),[3 2 1])),2)),2),:)
另一个非常接近,但仍然避免
两个排列
一个排列
-

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

感谢你的努力你的答案很好
setdiff
是最好的解决方案,但要将您的第一次尝试转换为
any
(保持循环),这就是Matlab的建议(在您的情况下,您实际上希望
all
,而不是
any
):
A(all(A==B(k,2),:)=[]顺便说一句,我没有意识到你只是在比较前两列,所以请将我最后的评论更新为
A(all(A(:,1:2)==B(k,1:2),2),:)=[]谢谢大家的回答=)最初的运行时间(加上我的数据)是:0.198072秒。通过使用
bsxfun
方法,我获得了大约0.007秒的运行时间。通过使用
setdiff(A(:,1:2),B(:,1:2),'rows')
我得到了运行时间:0.004120秒。@jjepsoumi希望你也能在更大的数据量上做一些基准测试,看到这些结果也会很有趣。+1@Divakar我将尝试使用不同的数据集并发布我的结果=)这需要几分钟=)+1,但你不需要
setdiff(A)吗(:,1:2),B(:,1:2),‘行’
取而代之的是?当我写我的答案时,问题中有一个例子,两个数组与答案中的数组相似,现在被编辑掉了。我总是这样写:“例如,…”如果你理解了答案,你还是可以把它应用到这个问题上。@JJEPSUMI可以在编辑之前把你在帖子中的截图发回来吗?从所有的混乱中,我想到了一个替代的解决方案,
ismember
…:)@natan haha避免混乱的方法!+1之外:)@natan哈哈谢谢,这里也是:)
[ignore, ia] = setdiff( A(:,1:2), B(:,1:2), 'rows', 'stable' );
A = A( ia, : ); % keeping only relevant rows, beyond first two columns.
A(~any(squeeze(all(bsxfun(@eq,A(:,1:2),permute(B(:,1:2),[3 2 1])),2)),2),:)
A(~any(all(bsxfun(@eq,A(:,1:2),permute(B(:,1:2),[3 2 1])),2),3),:)