我正在寻找一种重新排序技术,将邻接矩阵的连通分量组合在一起。
例如,我用蓝色和绿色两组进行了说明。最初,'1的条目分布在矩阵的行和列中。通过重新排序行和列,所有'1'可以位于矩阵的两个连续部分中,更清楚地显示蓝色和绿色分量。
我不记得这种重新排序技术是什么。我搜索了邻接矩阵,集团,排序和重新排序的许多组合。
我发现的最接近的点击是
symrcm
将元素移近对角线,但不会创建组。
Is there a way to reorder the rows and columns of matrix to create a dense corner, in R?专注于删除完全空的行和列
请提供此技术的通用名称,以便我可以更有效地谷歌,或指向我的Matlab功能的方向。
答案 0 :(得分:2)
我不知道是否有更好的替代品可以直接给你结果,但这里有一种方法可以达到你的目的。
您的意见:
>> A
A =
0 1 1 0 1
1 0 0 1 0
0 1 1 0 1
1 0 0 1 0
0 1 1 0 1
将第一行和第一列作为列掩码(
maskCol
)和 行掩码(maskRow
)。
获取掩码,其中第一行和第一列中包含一些的值
maskRow = A(:,1)==1;
maskCol = A(1,:)~=1;
重新排列行(根据行掩码)
out = [A(maskRow,:);A(~maskRow,:)];
给出这样的东西:
out =
1 0 0 1 0
1 0 0 1 0
0 1 1 0 1
0 1 1 0 1
0 1 1 0 1
重新排列列(根据列掩码)
out = [out(:,maskCol),out(:,~maskCol)]
给出了预期的结果:
out =
1 1 0 0 0
1 1 0 0 0
0 0 1 1 1
0 0 1 1 1
0 0 1 1 1
只是检查指数是否应该是它们应该在哪里,或者你是否想要相应的重新安排指数;)
重新安排之前:
idx = reshape(1:25,5,[])
idx =
1 6 11 16 21
2 7 12 17 22
3 8 13 18 23
4 9 14 19 24
5 10 15 20 25
重新安排后(我们之前做过的同样的过程)
outidx = [idx(maskRow,:);idx(~maskRow,:)];
outidx = [outidx(:,maskCol),outidx(:,~maskCol)]
<强>输出:强>
outidx =
2 17 7 12 22
4 19 9 14 24
1 16 6 11 21
3 18 8 13 23
5 20 10 15 25
对于通用案例,如果您事先不知道矩阵,请按以下步骤查找maskRow
和maskCol
使用的逻辑:
第一排。将其视为列掩码(
maskCol
)。对于第2行到最后一行,重复以下过程。
将当前行与
maskCol
进行比较。如果任何一个值与
maskCol
匹配,则找到该元素 明智的逻辑OR并将其更新为新的maskCol
重复此过程直至最后一行。
- 醇>
在使用列时查找
maskRow
的相同过程 而是迭代。
<强>代码:强>
%// If you have a square matrix, you can combine both these loops into a single loop.
maskCol = A(1,:);
for ii = 2:size(A,1)
if sum(A(ii,:) & maskCol)>0
maskCol = maskCol | A(ii,:);
end
end
maskCol = ~maskCol;
maskRow = A(:,1);
for ii = 2:size(A,2)
if sum(A(:,ii) & maskRow)>0
maskRow = maskRow | A(:,ii);
end
end
以下是尝试此操作的示例:
%// Here I removed some 'ones' from first, last rows and columns.
%// Compare it with the original example.
A = [0 0 1 0 1
0 0 0 1 0
0 1 1 0 0
1 0 0 1 0
0 1 0 0 1];
然后,重复之前遵循的程序:
out = [A(maskRow,:);A(~maskRow,:)]; %// same code used
out = [out(:,maskCol),out(:,~maskCol)]; %// same code used
结果如下:
>> out
out =
0 1 0 0 0
1 1 0 0 0
0 0 0 1 1
0 0 1 1 0
0 0 1 0 1
注意:此方法可能适用于大多数情况,但在某些罕见情况下仍可能失败。
这是一个例子:
%// this works well.
A = [0 0 1 0 1 0
1 0 0 1 0 0
0 1 0 0 0 1
1 0 0 1 0 0
0 0 1 0 1 0
0 1 0 0 1 1];
%// This may not
%// Second col, last row changed to zero from one
A = [0 0 1 0 1 0
1 0 0 1 0 0
0 1 0 0 0 1
1 0 0 1 0 0
0 0 1 0 1 0
0 0 0 0 1 1];
为什么会失败?
当我们遍历每一行(以查找列掩码)时,例如,当我们移动到第3行时,没有cols与第一行匹配(当前
maskCol
)。因此,第3行(第2个元素)携带的唯一信息将丢失。这可能是极少数情况,因为某些其他行可能仍包含相同的信息。见第一个例子。第三行中没有一个元素与第一行匹配,但由于最后一行具有相同的信息(第二个元素为1),因此它给出了正确的结果。只有在极少数情况下,可能会发生类似的情况。知道这个缺点仍然很好。
这是蛮力替代品。如果您认为前一种情况可能会失败,则可以应用。在这里,我们使用
while loop
运行前面的代码(查找行和col掩码),并使用更新的maskCol
,以便找到正确的掩码。
<强>步骤:强>
maskCol = A(1,:);
count = 1;
while(count<3)
for ii = 2:size(A,1)
if sum(A(ii,:) & maskCol)>0
maskCol = maskCol | A(ii,:);
end
end
count = count+1;
end
采用上一个示例(前一个方法失败的地方)并使用和不使用while-loop
没有蛮力:
>> out
out =
1 0 1 0 0 0
1 0 1 0 0 0
0 0 0 1 1 0
0 1 0 0 0 1
0 0 0 1 1 0
0 0 0 0 1 1
使用Brute-Forcing while循环:
>> out
out =
1 1 0 0 0 0
1 1 0 0 0 0
0 0 0 1 1 0
0 0 1 0 0 1
0 0 0 1 1 0
0 0 0 0 1 1
获得正确结果所需的迭代次数可能会有所不同。但是拥有一个好的数字是安全的。
祝你好运!