我想将多个关系圆(由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
仅返回最后一次迭代(circle_5
)的边列表,而前三个被覆盖。
此外,假设这五个圆是从一组50个人中绘制的,那么如何将这种边缘列表的值映射到50 x 50邻接矩阵的相应单元格中? (我想make_graph
中的as_adjacency_matrix
和igraph
函数应该可以解决问题,但目前我还不知道该怎么做)
另外,对于重叠的成员资格,例如circle_1
和circle_5
中的(1,3),意味着1和3在此50人的网络中链接两次。如何汇总此计数频率并将邻接矩阵转换为加权矩阵?
答案 0 :(得分:2)
您可以通过合并边缘列表来完成此操作,然后直接创建矩阵。
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创建
答案 1 :(得分:1)
我从@gfgm借用了顶点列表(“圆”),并使用了igraph
函数。
使用lapply
遍历顶点列表。对于每组顶点,创建一个完整图形(make_full_graph
),其顶点数n
等于向量的长度。设置顶点的名称(V(g)$name
)。转换为“边缘列表”(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