根据等价

时间:2015-05-18 15:19:36

标签: arrays matlab matrix-indexing

我有一个Nx2矩阵(在本例中为6X2),如下所示:

5  4
8  6
9  8 
10 9
15 14
16 15

我想以下列方式对它们进行分组:

*(5,4)是第1组。用剩余的行检查它。由于5或4都没有出现在剩余的行中,因此可以保持不变。

*(8,6)是下一组。然而在第3行中,8再次出现为(9,8)。所以它连接到第二组,即第二组变为(8,6,9,8)。

*下一个(10,9)。但是9属于第2组,也有10个。所以第二组现在是(8,6,9,8,10,9)。

*下一个(15,14)被看到。到目前为止还没有出现或重复过。所以它成为第3组,即(15,14)。

*最后,看到了(16,15)。但是由于第3组中已经重复了15次,所以该组现在更新为(15,14,16,15)。

最后,MATLAB中的unique命令可用于删除组中的冗余元素。

我希望最终输出为No of groups:

5   4
8   6   9   10
15  14  16

注意:行方式组中元素的顺序并不重要,因为(5,4)或(4,5)是相同的。我猜也是,最后的输出可能附加零,以使其成为相同尺寸的矩阵,即

5   4   0   0 
8   6   9  10 
15 14  16   0

请帮助。谢谢。

2 个答案:

答案 0 :(得分:1)

这让我想起了一般的集群化问题。 Cuthill-McKee算法正是您搜索的算法,尽管它通常以不同的术语表达。好消息是Matlab在symrcm函数中实现了它。

这是一段与你的例子一起使用的代码。请注意,它非常强大,并且还能够处理更复杂的数据集:

% --- Definition
D = [5 4 ; 8 6 ; 9 8 ; 10 9 ; 15 14 ; 16 15];
N = max(D(:));
U = unique(D(:));

% --- Tansformation to adjacency matrix
A = sparse(N,N);

% Diagonal element
for i = 1:numel(U)
    A(U(i),U(i)) = 1;
end

% Adjacency links
for i = 1:size(D,1)
    A(D(i,1),D(i,2)) = 1;
    A(D(i,2),D(i,1)) = 1;
end

% --- Cuthill Mc-Kee algorithm
r = symrcm(A);

% --- Find the clusters

% Preparation
B = (A(r,r)^N)>0;
i = 1;
C = {};

% Find clusters iteratively
while i<=N

     if ~any(B(:,i))
         i = i+1;
     else
         I = find(B(:,i));
         i = max(I)+1;
         C{end+1} = r(I);
     end

end

% --- Display
for i = 1:numel(C)
    disp(C{i})
end

和输出:

5     4
10     9     8     6    
16    15    14

最佳,

答案 1 :(得分:1)

所以,我觉得应该有一种方法可以使用基于树的算法或不相交集/联合查找类型方法来实现。但是对于一个肮脏的第一种方法,可能不是那么有效,我编写了以下内容:

A = [5 4
     8 6
     9 8     
    10 9
    15 14
    16 15
     8 8
     3 4
     3 1
     ];
B = mat2cell(A,ones(size(A,1),1),2);

iter = 1;
while(true)
    if (iter > size(B,1))
        break
    end
    y = B{iter};
    C = cat(1,false(iter,1),cellfun(@(x) any(sum(bsxfun(@eq,x,y'))),B(iter+1:end)));
    if any(C)
        B{iter} = (cat(2,B{iter}, B{C}));
        % or put you can start shortening them here, by calling unique() already:
        %B{iter} = unique(cat(2,B{iter}, B{C}));
        B(C) = [];
    else
        iter = iter+1;
    end
end

B = cellfun(@unique,B,'uni',false);
B{:}

效果很好。我不知道这是否适合你想要的东西,但快速编码很有趣。感谢有趣的问题。