查找Matlab中矩阵的行是否“落在”另一个矩阵的行内

时间:2018-08-31 15:40:07

标签: matlab

我在Matlab中有一个大小为Ksets的矩阵Gx(l*N)和一个大小为A的矩阵MxN

Ksets的每一行都可以分解为大小为l的{​​{1}}子行。

让我用一个例子更好地解释。

1xN

在示例中:

    clear N=3; l=4; G=2; M=5; Ksets=[1 2 3 5 6 7 9 10 11 0 0 0; 13 14 15 1 2 3 21 22 23 1 1 1]; %Gx(l*N) A=[1 2 3; 5 6 7; 21 22 23; 1 2 3; 0 0 0]; %MxN
  • 1由大小为Ksets的{​​{1}}个子行组成:l1xN,{ {1}},[1 2 3]

  • [5 6 7]
  • [9 10 11]由大小为[0 0 0]的{​​{1}}个子行组成:2Ksets,{ {1}},l

我假设1xN的每一行不包含相等的子行。

如果行[13 14 15]等于[1 2 3]子行之一,我希望您能帮助构建一个[21 22 23]大小为[1 1 1]的矩阵Ksets -Response行,否则为零。

继续上面的示例

GxM

这段代码可以满足我的要求:

Response(g,m)=1

我的代码由2个循环组成,这是不希望的,因为在我的实际算法中,A(m,:)非常大。您有没有循环的建议吗?

2 个答案:

答案 0 :(得分:1)

进行矢量化非常困难,尤其是如果您要比较的子集嵌入在每一行中。为了提高效率,可以将Ksets更改为3D矩阵,其中每个切片包含格式化为2D矩阵的子集,其中每个子集都基于行。然后,您可以将ismember与每行仅使用一个循环结合使用,并填充结果。

Ksets2 = permute(reshape(Ksets.', [N l G]), [2 1 3]);
Response = false(G, M);
for i = 1 : G
    Response(i, :) = ismember(A, Ksets2(:,:,i), 'rows')';
end

第一条语句会重塑您的数据,使其成为3D矩阵,但是由于MATLAB的列主要处理,并且因为您的子集位于行主要,所以我们必须在重塑之前转置数据。但是,这导致每一列都在一个子集中,因此我们必须使用permute操作独立地转置每个切片。

完成后,我们分配所需大小的矩阵,然后遍历Ksets中的每一行(现已转换为子集的行)以产生所需的结果。

我们得到:

>> Response

Response =

  2×5 logical array

   1   1   0   1   1
   1   0   1   1   0

答案 1 :(得分:1)

可以进行一些调整和尺寸置换:

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

其工作原理如下:

  1. reshape(Ksets.', N, [], G)Ksets整形为N×l×G 3D数组,以便每个子行现在都彼此分开。
  2. bsxfun(@eq, ..., permute(A, [2 3 4 1]))创建一个N×l×G×M 4D数组,并比较步骤3D数组中每个元素的结果1,每个值在A中。
  3. all(..., 1)测试每个子行(即第一维)的 all 个元素是否匹配。 any(...,2)测试是否发生在原始行之一(即第二维)的 any 子行中。
  4. permute(..., [3 4 1 2])除去前两个维(在步骤3中变为单例),得到所需的G×M结果。 (为此使用squeeze是不安全的,因为如果使用G=1,它将错误地删除三维尺寸。)