将带有 ids 的图形转换为其在 Matlab 中的索引

Transform a graph with ids to its index in Matlab

我有一个 Nx2 矩阵,其中包含来自图形的边。矩阵的索引对应于推特用户的 ID。他们的关系是转推状态(如果用户转推另一个用户)。在我的图表中完全存在 N 转推关系。用户数是 M。我想将图表的 id 从最初的 twitter id 转换为 1:M id。例如,将图形的第一个 id 替换为 1(在存在的每一行和每一列中)。我想这样做,而不是再次更改已经更改过的 id。我尝试将 for 循环与 find 函数结合使用,以便将 id 转换为索引。但是,我应该怎么做才能避免更改已经更改的项目?我知道我的代码是错误的:

counter = 0;
for index = 1:length(grph)
   index1 =  find(grph(:,1) == grph(index,1));
   index2 =  find(grph(:,2) == grph(index,2));

   counter = counter+1;
   grph(index1,1)  = counter;
   counter = counter+1;
   grph(index2,2) = counter;
end

一个小例子说明了我想要的,如下:

35113   45010   
5695    57711   
22880   33193   
22880   45010   
43914   35113   

期望的输出:

1 2
3 4
5 6
5 2
7 1

我现在无法测试,但这应该可以满足您的要求:

[~, ~, kk] = unique(A.','stable');
result = reshape(kk, fliplr(size(A))).';

您需要足够新的 Matlab 版本,以便 unique 具有 'stable' 选项。

如果您有通讯工具箱,第二行可以替换为

result = vec2mat(kk, size(A,2));

很简单。使用 unique and reshape 的组合。假设您示例中的 ID 矩阵存储在 A:

[~,~,B] = unique(A.', 'stable');
C = reshape(B, [size(A,2) size(A,1)]).';

A 将是 ID 矩阵,而 C 是您想要的输出。这是如何工作的,unique 的第三个输出将为您提供在 A 中遇到的每个值的唯一 ID 数组。之所以要先转置结果,是因为MATLAB是按列运算的,而你的结果需要按行运算。转置结果有效地做到了这一点。此外,您需要 'stable' 标志,以便我们按照遇到它们的顺序分配 ID。不做 'stable' 将首先 排序 A 中的值,然后分配 ID。

B 将不可避免地成为列向量,因此我们需要 reshape 将其返回到与您的输入 A 大小相同的矩阵。请注意,我需要通过结果的 转置 进行整形,因为 reshape 将在列之间进行操作。因为我们是按行操作的,所以我需要通过转置来重塑矩阵,然后转置该结果以获得您想要的输出。

使用示例:

A = [35113   45010
5695    57711
22880   33193
22880   45010
43914   35113]; %// Matrix defined by you
[~,~,B] = unique(A.', 'stable');
C = reshape(B, [size(A,2) size(A,1)]).';

C =

     1     2
     3     4
     5     6
     5     2
     7     1

但是,如果不需要对 ID 进行排序并且您只想为每个节点 ID 分配 ID,那么您可以直接使用 unique 而无需 stable 标志。

现在,如果您想知道图表中的哪些 ID 分配给了输出矩阵中的哪些 ID,只需使用 unique:

的第一个输出
[mapping, ~, B] = unique(A.', 'stable');

mapping 将为您提供矩阵中遇到的所有唯一 ID 的列表。他们的位置标识了用于将他们分配到 B 中的 ID。也就是说,运行这个,我们得到:

mapping =

       35113
       45010
        5695
       57711
       22880
       33193
       43914

这意味着 A 中的 ID 35113 映射到 B 中的 1,A 中的 ID 45010 映射到 B 中的 2,依此类推。作为更详细的说明:

mappings = [(1:numel(mapping)).' mapping]

mappings =

           1       35113
           2       45010
           3        5695
           4       57711
           5       22880
           6       33193
           7       43914