如何在matlab中找到矩阵中每一行的重复索引?

7

我希望找到矩阵中所有有重复的行的索引。例如:

A = [1 2 3 4
     1 2 3 4
     2 3 4 5
     1 2 3 4
     6 5 4 3]

要返回的向量将是[1,2,4]
许多类似的问题建议使用unique函数,我尝试过,但最接近我想要的是:
[C, ia, ic] = unique(A, 'rows')

ia = [1 3 5]
m = 5;
setdiff(1:m,ia) = [2,4]

但是使用 unique 我只能提取一行的第二、第三、第四等实例,我还需要获取第一个实例。有没有办法可以做到这一点?

注:它必须是一种不涉及循环遍历行的方法,因为我正在处理大型稀疏矩阵。


现在没时间,但首先使用unique,然后在那些被发现为重复的元素上使用ismember。 - Dennis Jaheruddin
3个回答

4
怎么样:
[~, ia, ic] = unique(A, 'rows')

setdiff(1:size(A,1), ia( sum(bsxfun(@eq,ic,(1:max(ic))))<=1 ))

很棒的问答!这是一种聪明的方法来找到有多个重复出现的行。 - chappjc

4

还有其他三种可能性:

  1. Sort rows of the matrix (with sortrows), detect equal rows (with diff) and use indexing to undo the sorting:

    [As inds] = sortrows(A);
    ind = find(all(diff(As)==0,2));
    result = inds(union(ind,ind+1));
    
  2. Directly compare every row against every other row (with bsxfun):

    match = squeeze(all((bsxfun(@eq, A, permute(A, [3 2 1]))), 2));
    result = find(any(match - eye(size(A,1))));
    
  3. Use pdist with Hamming distance instead of bsxfun:

    match = ~squareform(pdist(A,'hamming'));
    result = find(any(match - eye(size(A,1))));
    
方法二和方法三的优点是,你可以获得一个(对称)矩阵 match,它告诉你哪些行相等。以你的示例为例,
    >> match
    match =
      1     1     0     1     0
      1     1     0     1     0
      0     0     1     0     0
      1     1     0     1     0
      0     0     0     0     1

方法2看起来像是一个赢家。 - Dan
方法2是小矩阵的好解决方案,但是当我尝试在大矩阵上运行时,出现“使用permute时出错,不支持ND-sparse数组”的错误。当我尝试使用方法1解决大问题时,我的电脑崩溃了:P - Matt Harris
@MattHarris 我添加了一个新的方法,类似于第2种方法,但避免生成大型3D数组。它可能具有更高的内存效率。 - Luis Mendo
setdiff 结合 bsxfun 可能是最佳选择,但如果有其他 3 种好的解决方案也会得分。 - chappjc
@chappjc 嘿!欢迎回来 :-) - Luis Mendo
我不会说“回头”...也许在接下来的几周里我能找到另外30秒钟。 :P - chappjc

3

一个识别重复项的方法是对来自uniqueic向量应用accumarray,然后setdiff将返回重复行的完整索引列表。

[~, ia, ic] = unique(A,'rows')
dupRows = setdiff(1:size(A,1),ia(accumarray(ic,1)<=1))


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接