找到两个 Matlab 矩阵之间的相等行

Find equal rows between two Matlab matrices

我在 Matlab 中有一个大小为 GxN 的矩阵 index 和一个大小为 MxN 的矩阵 A

让我在提出问题之前先举个例子。

clear
N=3;
G=2;
M=5;

index=[1  2  3;
       13 14 15]; %GxN

A=[1  2  3; 
   5  6  7; 
   21 22 23; 
   1  2  3;
   13 14 15]; %MxN

如果行 A(m,:) 等于 index(g,:) 且为零,我希望你帮助构建一个大小为 GxMResponse(g,m)=1 的矩阵 Response除此以外。

继续上面的例子

Response= [1 0 0 1 0; 
           0 0 0 0 1]; %GxM

这段代码做了我想要的(取自 - 只是为了澄清:当前的问题是不同的)

Response=permute(any(all(bsxfun(@eq, reshape(index.', N, [], G), permute(A, [2 3 4 1])), 1), 2), [3 4 1 2]);

但是,对于我的实际矩阵大小 (N=19, M=500, G=524288),该命令非常慢。我知道我无法获得巨大的速度,但欢迎任何可以改进的东西。

MATLAB 有很多函数 working with sets, including setdiff, intersect, union etc. In this case, you can use the ismember 函数:

[~, Loc] = ismember(A,index,'rows');

给出:

Loc =
     1
     0
     0
     1
     2

Response的构造如下:

Response = (1:size(index,1) == Loc).';

Response =
  2×5 logical array
   1   0   0   1   0
   0   0   0   0   1

方法一:计算距离

如果您有统计工具箱:

Response = ~(pdist2(index, A));

或:

Response = ~(pdist2(index, A, 'hamming'));

这是有效的,因为 pdist2 计算每对行之间的距离。相等的行的距离为 0。对于那些行对,逻辑否定 ~ 给出 1,否则给出 0

方法 2:将行减少为唯一的整数标签

这种方法在我的机器上更快:

[~,~,u] = unique([index; A], 'rows');
Response = bsxfun(@eq, u(1:G), u(G+1:end).');

它的工作原理是将行减少为唯一的整数标签(使用 unique 的第三个输出),然后比较后者而不是前者。

对于您的尺寸值,这在我的计算机上大约需要 1 秒:

clear
N = 19; M = 500; G = 524288;
index = randi(5,G,N); A = randi(5,M,N);
tic
[~,~,u] = unique([index; A], 'rows');
Response = bsxfun(@eq, u(1:G), u(G+1:end).');
toc

给予

Elapsed time is 1.081043 seconds.

您可以 reshape 矩阵,使每一行都位于第 3 个维度上。然后我们可以使用隐式扩展(参见 R2016b 或更早版本的 bsxfun)来使所有元素相等,并使用 all 在行上聚合(即,如果给定行不完全相等则为 false)。

Response = all( reshape( index, [], 1, size(index,2) ) == reshape( A, 1, [], size(A,2) ), 3 ); 

您甚至可以通过在另一个维度中使用 all 来避免一些重塑,但我更容易以这种方式形象化它。