在树图中获取 parents 向量的最快方法
Fastest way to get vector of parents in a tree graph
给定一个像这样的树图:
library(igraph)
g <- sample_pa(1000, power=1, directed=FALSE)
nodes <- V(g)[-1] # exclude root node since it has no parent.
最快 获取每个节点的 parent 的方法是什么?
我目前使用的是:
parents <- unlist(adjacent_vertices(g, nodes, mode = c("out")))
但这实际上是我的代码瓶颈之一,因为我需要对数千个图(每个约 50 个顶点)执行此操作。
首先,让我们在较小的图表上尝试一下,以便我们了解发生了什么:
library(igraph)
set.seed(144)
g <- sample_pa(20, power=1, directed=FALSE)
plot(g)
在你的图表中,每个节点都有一个父节点,所以我希望一个长度为 n-1
的向量用于具有 n
个节点的图表(在本例中为 19,在你提供的示例中为 999 ).你可以从边缘列表中高效地获取,选择第一列:
get.edgelist(g)[,1]
# [1] 1 1 2 3 3 2 4 1 6 1 9 6 2 6 2 1 1 8 7
从视觉上我们可以确认节点2的父节点是节点1,节点3的父节点是节点1,节点4的父节点是节点2,节点5的父节点是节点3,以此类推。
这将比对大图使用 adjacent_vertices
的方法更有效。例如,在您的大小为 1,000 的图形上,速度大约快 1,700 倍:
set.seed(144)
g <- sample_pa(1000, power=1, directed=FALSE)
nodes <- V(g)[-1] # exclude root node since it has no parent.
library(microbenchmark)
microbenchmark(get.edgelist(g)[,1], unlist(adjacent_vertices(g, nodes, mode = c("out"))))
# Unit: microseconds
# expr min lq mean median uq max neval
# get.edgelist(g)[, 1] 84.558 110.891 262.4235 125.497 169.947 9673.282 100
# unlist(adjacent_vertices(g, nodes, mode = c("out"))) 303523.390 350459.141 455860.3464 444960.802 528314.593 754882.895 100
此外,您的示例 returns 本示例中长度为 1,965 的向量甚至认为该图有 999 条边。这是因为大多数边由您的代码返回两次,每个端点一次。
如果您真的希望所有 1,965 个值都完全按照您在问题中提供的代码中返回,您仍然可以使用 get.edgelist
:
显着加快操作速度(750 倍)
match.op.output <- function(g) {
el <- get.edgelist(g)
el <- rbind(el, el[,2:1])
el <- el[order(el[,1], el[,2]),]
el[el[,1] != 1,2]
}
all.equal(match.op.output(g), unlist(adjacent_vertices(g, nodes, mode = c("out"))))
# [1] TRUE
microbenchmark(match.op.output(g), unlist(adjacent_vertices(g, nodes, mode = c("out"))))
# Unit: microseconds
# expr min lq mean median uq max neval
# match.op.output(g) 541.416 585.5115 692.889 652.18 744.0785 1437.427 100
# unlist(adjacent_vertices(g, nodes, mode = c("out"))) 382952.446 429673.4950 507641.095 486633.23 554715.5570 749883.994 100
给定一个像这样的树图:
library(igraph)
g <- sample_pa(1000, power=1, directed=FALSE)
nodes <- V(g)[-1] # exclude root node since it has no parent.
最快 获取每个节点的 parent 的方法是什么?
我目前使用的是:
parents <- unlist(adjacent_vertices(g, nodes, mode = c("out")))
但这实际上是我的代码瓶颈之一,因为我需要对数千个图(每个约 50 个顶点)执行此操作。
首先,让我们在较小的图表上尝试一下,以便我们了解发生了什么:
library(igraph)
set.seed(144)
g <- sample_pa(20, power=1, directed=FALSE)
plot(g)
在你的图表中,每个节点都有一个父节点,所以我希望一个长度为 n-1
的向量用于具有 n
个节点的图表(在本例中为 19,在你提供的示例中为 999 ).你可以从边缘列表中高效地获取,选择第一列:
get.edgelist(g)[,1]
# [1] 1 1 2 3 3 2 4 1 6 1 9 6 2 6 2 1 1 8 7
从视觉上我们可以确认节点2的父节点是节点1,节点3的父节点是节点1,节点4的父节点是节点2,节点5的父节点是节点3,以此类推。
这将比对大图使用 adjacent_vertices
的方法更有效。例如,在您的大小为 1,000 的图形上,速度大约快 1,700 倍:
set.seed(144)
g <- sample_pa(1000, power=1, directed=FALSE)
nodes <- V(g)[-1] # exclude root node since it has no parent.
library(microbenchmark)
microbenchmark(get.edgelist(g)[,1], unlist(adjacent_vertices(g, nodes, mode = c("out"))))
# Unit: microseconds
# expr min lq mean median uq max neval
# get.edgelist(g)[, 1] 84.558 110.891 262.4235 125.497 169.947 9673.282 100
# unlist(adjacent_vertices(g, nodes, mode = c("out"))) 303523.390 350459.141 455860.3464 444960.802 528314.593 754882.895 100
此外,您的示例 returns 本示例中长度为 1,965 的向量甚至认为该图有 999 条边。这是因为大多数边由您的代码返回两次,每个端点一次。
如果您真的希望所有 1,965 个值都完全按照您在问题中提供的代码中返回,您仍然可以使用 get.edgelist
:
match.op.output <- function(g) {
el <- get.edgelist(g)
el <- rbind(el, el[,2:1])
el <- el[order(el[,1], el[,2]),]
el[el[,1] != 1,2]
}
all.equal(match.op.output(g), unlist(adjacent_vertices(g, nodes, mode = c("out"))))
# [1] TRUE
microbenchmark(match.op.output(g), unlist(adjacent_vertices(g, nodes, mode = c("out"))))
# Unit: microseconds
# expr min lq mean median uq max neval
# match.op.output(g) 541.416 585.5115 692.889 652.18 744.0785 1437.427 100
# unlist(adjacent_vertices(g, nodes, mode = c("out"))) 382952.446 429673.4950 507641.095 486633.23 554715.5570 749883.994 100