Return R中每对节点之间的相互节点列表
Return a list of mutual nodes between every pair of nodes in R
我想获得图中每对节点之间相互连接的节点列表:
library(igraph)
G <- graph(c(1,2,1,3,1,4,2,4, 2,3,2,5,3,5,4,5,5,6,5,7,7,8,7,9), directed=F)
plot(G)
- 边是无向的。
例如,在此图中,节点 1 和 2 共享公共节点 3 和 4。节点 1 和 3 共享公共节点 2。我想获取此列表或作为数据框的格式..
是否有一个命令可以获取类似以下任一内容的命令:
(1)
node1 node2 mutual
1 2 3, 4
1 3 2
1 4 2
2 3 1, 5
或 (2)
node1 node2 mutual
1 2 3
1 2 4
1 3 2
1 4 2
2 3 1
2 3 5
我能够使用此代码获得两个节点之间的相互节点数:
# function to count the number of mutual friends between every pair of nodes
mutual_friends <- function(G) {
# initialize an emptry matrix to store number of mutual friends between pairs of nodes
num_nodes <- vcount(G)
mutual_friends <- matrix(0, nrow=num_nodes, ncol=num_nodes)
# loop over each node
for (node in 1:num_nodes) {
# get this node's list of friends
friends <- neighbors(G, node)
# add a count of 1 between all pairs of the node's friends
for (i in friends)
for (j in friends)
mutual_friends[i, j] = mutual_friends[i, j] + 1
}
# make the output readable with column names
dimnames(mutual_friends) <- list(row=V(G)$name, col=V(G)$name)
diag(mutual_friends) <- NA
mutual_friends
}
但我正在努力获取每对节点之间的相互节点列表。
我感谢任何形式的建议和帮助。谢谢!
这不是很有效,它是一个蛮力双循环,但你可以做到
get_mutuals <- function(g) {
do.call("rbind", lapply(seq.int(1, vcount(g)-1), function(i) {
do.call("rbind", lapply(seq.int(i+1, vcount(g)), function(j) {
ni <- neighbors(g, i)
nj <- neighbors(g, j)
overlap <- intersect(ni, nj)
if (length(overlap) & i %in% nj) {
data.frame(i=i, j=j, m=overlap)
} else {
NULL
}
}))
}))
}
get_mutuals(G)
这将为您提供类似于版本 2 的输出。
i j m
1 1 2 3
2 1 2 4
3 1 3 2
4 1 4 2
5 2 3 1
...
如果您想要更相似的东西,您可以切换到 data.frame(i=i, j=j, m=toString(overlap))
以将所有值粘贴到该列中。
另一种可能性是像这样迭代边
get_mutuals <- function(g) {
do.call("rbind", lapply(seq.int(1, gsize(g)), function(i) {
edge <- ends(g, i)
i <- edge[1, 1]
j <- edge[1, 2]
ni <- neighbors(g, i)
nj <- neighbors(g, j)
overlap <- intersect(ni, nj)
if (length(overlap)) {
data.frame(i=i, j=j, m=overlap)
} else {
NULL
}
}))
}
get_mutuals(G)
请注意,如果两个相邻节点共享一个公共邻居,则它们会形成一个三角形。函数 igraph::triangles
给出图形中的所有三角形。
library(dplyr)
triangle_matrix <- matrix(igraph::triangles(G), ncol = 3, byrow = TRUE)
gtools::permutations(3, 3) %>%
apply(1, function(x) list(triangle_matrix[, x])) %>%
unlist(recursive = FALSE) %>%
Reduce(rbind, .) %>%
as.data.frame() %>%
filter(V1 < V2) %>%
arrange(V1, V2, V3)
您可以通过以下方式继续管道获得 (1):
... %>% group_by(V1, V2) %>% summarise(mutual = list(V3))
更新
如果你想找出所有直接连接的节点与一个相互节点,你可以尝试triangles
in igraph
如下
do.call(
rbind,
apply(
matrix(triangles(G), nrow = 3),
2,
function(v) {
u <- t(sapply(seq_along(v), function(k) t(v[-k])))
setNames(data.frame(cbind(v, rbind(u, u[, 2:1]))), c("node1", "node2", "mutual"))
}
)
)
这给出了
node1 node2 mutual
1 5 2 3
2 2 5 3
3 3 5 2
4 5 3 2
5 2 3 5
6 3 2 5
7 5 2 4
8 2 5 4
9 4 5 2
10 5 4 2
11 2 4 5
12 4 2 5
13 2 1 4
14 1 2 4
15 4 2 1
16 2 4 1
17 1 4 2
18 4 1 2
19 2 1 3
20 1 2 3
21 3 2 1
22 2 3 1
23 1 3 2
24 3 1 2
也许你可以像下面那样尝试ego
setNames(
data.frame(do.call(
rbind,
lapply(
Filter(
function(x) length(x) > 2,
ego(G)
),
function(v) {
cbind(t(combn(v[-1], 2)), v[1])
}
)
)),
c("node1", "node2", "mutual")
)
这给出了
node1 node2 mutual
1 2 3 1
2 2 4 1
3 3 4 1
4 1 3 2
5 1 4 2
6 1 5 2
7 3 4 2
8 3 5 2
9 4 5 2
10 1 2 3
11 1 5 3
12 2 5 3
13 1 2 4
14 1 5 4
15 2 5 4
16 2 3 5
17 2 4 5
18 2 6 5
19 2 7 5
20 3 4 5
21 3 6 5
22 3 7 5
23 4 6 5
24 4 7 5
25 6 7 5
26 5 8 7
27 5 9 7
28 8 9 7
我想获得图中每对节点之间相互连接的节点列表:
library(igraph)
G <- graph(c(1,2,1,3,1,4,2,4, 2,3,2,5,3,5,4,5,5,6,5,7,7,8,7,9), directed=F)
plot(G)
- 边是无向的。
例如,在此图中,节点 1 和 2 共享公共节点 3 和 4。节点 1 和 3 共享公共节点 2。我想获取此列表或作为数据框的格式..
是否有一个命令可以获取类似以下任一内容的命令:
(1)
node1 node2 mutual
1 2 3, 4
1 3 2
1 4 2
2 3 1, 5
或 (2)
node1 node2 mutual
1 2 3
1 2 4
1 3 2
1 4 2
2 3 1
2 3 5
我能够使用此代码获得两个节点之间的相互节点数:
# function to count the number of mutual friends between every pair of nodes
mutual_friends <- function(G) {
# initialize an emptry matrix to store number of mutual friends between pairs of nodes
num_nodes <- vcount(G)
mutual_friends <- matrix(0, nrow=num_nodes, ncol=num_nodes)
# loop over each node
for (node in 1:num_nodes) {
# get this node's list of friends
friends <- neighbors(G, node)
# add a count of 1 between all pairs of the node's friends
for (i in friends)
for (j in friends)
mutual_friends[i, j] = mutual_friends[i, j] + 1
}
# make the output readable with column names
dimnames(mutual_friends) <- list(row=V(G)$name, col=V(G)$name)
diag(mutual_friends) <- NA
mutual_friends
}
但我正在努力获取每对节点之间的相互节点列表。 我感谢任何形式的建议和帮助。谢谢!
这不是很有效,它是一个蛮力双循环,但你可以做到
get_mutuals <- function(g) {
do.call("rbind", lapply(seq.int(1, vcount(g)-1), function(i) {
do.call("rbind", lapply(seq.int(i+1, vcount(g)), function(j) {
ni <- neighbors(g, i)
nj <- neighbors(g, j)
overlap <- intersect(ni, nj)
if (length(overlap) & i %in% nj) {
data.frame(i=i, j=j, m=overlap)
} else {
NULL
}
}))
}))
}
get_mutuals(G)
这将为您提供类似于版本 2 的输出。
i j m
1 1 2 3
2 1 2 4
3 1 3 2
4 1 4 2
5 2 3 1
...
如果您想要更相似的东西,您可以切换到 data.frame(i=i, j=j, m=toString(overlap))
以将所有值粘贴到该列中。
另一种可能性是像这样迭代边
get_mutuals <- function(g) {
do.call("rbind", lapply(seq.int(1, gsize(g)), function(i) {
edge <- ends(g, i)
i <- edge[1, 1]
j <- edge[1, 2]
ni <- neighbors(g, i)
nj <- neighbors(g, j)
overlap <- intersect(ni, nj)
if (length(overlap)) {
data.frame(i=i, j=j, m=overlap)
} else {
NULL
}
}))
}
get_mutuals(G)
请注意,如果两个相邻节点共享一个公共邻居,则它们会形成一个三角形。函数 igraph::triangles
给出图形中的所有三角形。
library(dplyr)
triangle_matrix <- matrix(igraph::triangles(G), ncol = 3, byrow = TRUE)
gtools::permutations(3, 3) %>%
apply(1, function(x) list(triangle_matrix[, x])) %>%
unlist(recursive = FALSE) %>%
Reduce(rbind, .) %>%
as.data.frame() %>%
filter(V1 < V2) %>%
arrange(V1, V2, V3)
您可以通过以下方式继续管道获得 (1):
... %>% group_by(V1, V2) %>% summarise(mutual = list(V3))
更新
如果你想找出所有直接连接的节点与一个相互节点,你可以尝试triangles
in igraph
如下
do.call(
rbind,
apply(
matrix(triangles(G), nrow = 3),
2,
function(v) {
u <- t(sapply(seq_along(v), function(k) t(v[-k])))
setNames(data.frame(cbind(v, rbind(u, u[, 2:1]))), c("node1", "node2", "mutual"))
}
)
)
这给出了
node1 node2 mutual
1 5 2 3
2 2 5 3
3 3 5 2
4 5 3 2
5 2 3 5
6 3 2 5
7 5 2 4
8 2 5 4
9 4 5 2
10 5 4 2
11 2 4 5
12 4 2 5
13 2 1 4
14 1 2 4
15 4 2 1
16 2 4 1
17 1 4 2
18 4 1 2
19 2 1 3
20 1 2 3
21 3 2 1
22 2 3 1
23 1 3 2
24 3 1 2
也许你可以像下面那样尝试ego
setNames(
data.frame(do.call(
rbind,
lapply(
Filter(
function(x) length(x) > 2,
ego(G)
),
function(v) {
cbind(t(combn(v[-1], 2)), v[1])
}
)
)),
c("node1", "node2", "mutual")
)
这给出了
node1 node2 mutual
1 2 3 1
2 2 4 1
3 3 4 1
4 1 3 2
5 1 4 2
6 1 5 2
7 3 4 2
8 3 5 2
9 4 5 2
10 1 2 3
11 1 5 3
12 2 5 3
13 1 2 4
14 1 5 4
15 2 5 4
16 2 3 5
17 2 4 5
18 2 6 5
19 2 7 5
20 3 4 5
21 3 6 5
22 3 7 5
23 4 6 5
24 4 7 5
25 6 7 5
26 5 8 7
27 5 9 7
28 8 9 7