将几个节点向量合并到一个边列表中并将它们转换为邻接矩阵

Merging several vectors of nodes into an edgelist and convert them to an adjacency matrix

我想将多个关系圈(由 id 的列表组成)映射到一个大的邻接矩阵中。我的数据看起来像这样

circle_1 = c(1, 3, 5)
circle_2 = c(17, 22, 35, 49)
circle_3 = c(2, 9)
circle_4 = c(12, 28, 33)
circle_5 = c(1, 3, 8, 16, 40)

d_mat = matrix(ncol = 2)

for (i in 1:5) {
#extract id from list
dat = get(paste("circle", i, sep="_"))
#convert to edgelist, each pair is unique
dat_t = t(combn(dat, 2))
#rbind edge list together
edge_list <- rbind(d_mat, dat_t)
}

然而,输出edge_list仅returns来自最后一次迭代(circle_5)的边缘列表,前三个被覆盖。

此外,假设这五个圆圈是从一组 50 个人中抽取的,我如何将这些边列表的值映射到 50 x 50 邻接矩阵的相应单元格? (我想 make_graphas_adjacency_matrix 中的函数 igraph 应该可以解决问题,但我现在不知道怎么做)

此外,对于重叠成员,例如 circle_1circle_5 中的 (1, 3),这意味着 1 和 3 在这个 50 人网络中链接了两次。如何聚合此计数频率并将邻接矩阵转换为加权矩阵?

您可以像开始时那样合并边列表,然后直接创建矩阵。

circle_1 = c(1, 3, 5)
circle_2 = c(17, 22, 35, 49)
circle_3 = c(2, 9)
circle_4 = c(12, 28, 33)
circle_5 = c(1, 3, 8, 16, 40)

# lets put all the circles in a list for convenience
circles <- list(circle_1, circle_2, circle_3,
                circle_4, circle_5)

# we will lapply along the list, get the complete set of 
# edges with combn, and then rbind all the resulting
# structures together
edge_list <- do.call(rbind, lapply(circles, function(circ){t(combn(circ, 2))}))

# we convert to a data.frame and set the factor levels
# such that R knows these are nodes from a set of 50 nodes
edge_list <- data.frame(from = factor(edge_list[,1], levels=1:50),
                        to = factor(edge_list[,2], levels=1:50))
# take a look
head(edge_list)
#>   from to
#> 1    1  3
#> 2    1  5
#> 3    3  5
#> 4   17 22
#> 5   17 35
#> 6   17 49
# we can just use table to make the adjacency matrix. R will create
# a row/column for each level of the factor. We look at the first
# 6x6 entries
table(edge_list)[1:6,1:6] # luckily entry (1,3) = 2 as we hoped
#>     to
#> from 1 2 3 4 5 6
#>    1 0 0 2 0 1 0
#>    2 0 0 0 0 0 0
#>    3 0 0 0 0 1 0
#>    4 0 0 0 0 0 0
#>    5 0 0 0 0 0 0
#>    6 0 0 0 0 0 0

这个邻接矩阵是上三角矩阵。如果您希望邻接矩阵是对称的以反映无向图,您可以使用 adj.mat[lower.tri(adj.mat)] <- adj.mat[upper.tri(adj.mat)].

将矩阵的上下三角形设置为相等

如果您希望矩阵只是二进制的(而不是在不同的圈子中记录多个链接)只需 运行 通过 ifelse 语句:

# to convert to purely binary
adj.mat <- table(edge_list)
adj.mat.bin <- ifelse(adj.mat>1, 1, adj.mat)
adj.mat.bin[1:6,1:6]
#>     to
#> from 1 2 3 4 5 6
#>    1 0 0 1 0 1 0
#>    2 0 0 0 0 0 0
#>    3 0 0 0 0 1 0
#>    4 0 0 0 0 0 0
#>    5 0 0 0 0 0 0
#>    6 0 0 0 0 0 0

reprex package (v0.2.1)

创建于 2018-11-16

我从@gfgm 那里借用了顶点列表('circles')并使用了igraph 函数。

lapply 遍历顶点列表。对于每组顶点,创建一个完整图 (make_full_graph),其中顶点数 n 等于向量的长度。设置顶点的名称 (V(g)$name)。转换为 'edge list' (as_edgelist)。 rbind 结果矩阵。

library(igraph)
m <- do.call(rbind, lapply(circles, function(vert){
  g <- make_full_graph(n = length(vert))
  V(g)$name <- vert
  as_edgelist(g)
}))

设置factor层'from'和'to'顶点,并使用table(类似于@gfgm)

tt <- table(factor(m[ , 1], levels = 1:50),
            factor(m[ , 2], levels = 1:50)) 

t[1:8, 1:16]
#   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# 1 0 0 2 0 1 0 0 1 0  0  0  0  0  0  0  1
# 2 0 0 0 0 0 0 0 0 1  0  0  0  0  0  0  0
# 3 0 0 0 0 1 0 0 1 0  0  0  0  0  0  0  1
# 4 0 0 0 0 0 0 0 0 0  0  0  0  0  0  0  0
# 5 0 0 0 0 0 0 0 0 0  0  0  0  0  0  0  0
# 6 0 0 0 0 0 0 0 0 0  0  0  0  0  0  0  0
# 7 0 0 0 0 0 0 0 0 0  0  0  0  0  0  0  0
# 8 0 0 0 0 0 0 0 0 0  0  0  0  0  0  0  1