【问题标题】:Find equal rows between two Matlab matrices在两个 Matlab 矩阵之间找到相等的行
【发布时间】:2019-03-08 13:08:15
【问题描述】:

我在 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

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

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),该命令非常慢。我知道我将无法获得极快的速度,但欢迎任何可以改进的地方。

【问题讨论】:

  • 我非常怀疑这是否可以改进。您可以通过将代码分成几部分并计时来代替使用 1-liners 来做到这一点

标签: matlab performance matrix rows set-intersection


【解决方案1】:

方法 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.

【讨论】:

  • findgroups 可能比使用unique 的第三个输出更快。过去没有做过速度测试,但相信它会做同样的事情。
  • @Wolfie 我认为findgroups 需要将变量分组为向量。所以这里的矩阵必须被分成它们的列,这需要时间。另外,findgroups 内部使用了unique 的第三个输出,所以我怀疑它是否更快
  • 啊,那不理我了,没想到这两者是交织在一起的!第二个选项比我的重塑方法快很多,这让我感到惊讶。
  • @Wolfie 是的,对于 OP 的大小,您的方法比我在计算机上使用的第二种方法多 5 倍。我想当尺寸很大时,尽快减小尺寸(我的第二种方法)是有益的,即使这需要时间
【解决方案2】:

MATLAB 有很多working with sets 的函数,包括setdiffintersectunion 等。在这种情况下,您可以使用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
【解决方案3】:

您可以reshape 矩阵,以便每一行都位于第三维。然后我们可以使用隐式扩展(请参阅 R2016b 或更早版本的bsxfun)来实现所有元素的相等性,并使用all 对行进行聚合(即,如果给定行不完全相等,则为 false)。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    • 2021-03-07
    • 2021-09-20
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多