Return R 中 tidygraph objects 列表中的列表索引?

Return list index from a list of tidygraph objects in R?

所以,我有一个包含多个 tidygraph object 的列表,我想做的是 return 特定的索引 tidygraph object , select 由用户编辑。希望我下面的例子能解释这个问题。

(旁白:我尝试了下面显示的解决方案,但目前 运行 非常慢。我希望能提出一个不同的、更快的解决方案。)

首先,我创建了一些数据以转换为 tidygraph objects,然后我创建了 tidygraph objects 并将它们全部放在一个列表中:

library(tidygraph)

# create some data for the tbl_graph
nodes <- data.frame(name = c("Hadley", "David", "Romain", "Julia"),
                    level = c(1,1,1,1),
                    rank = c(1,1,1,1))

nodes1 <- data.frame(name = c("Hadley", "David", "Romain", "Julia"),
                    level = c(1,1,1,1),
                    rank = c(2,2,2,2))

nodes2 <- data.frame(name = c("Hadley", "David", "Romain", "Julia"),
                    level = c(1,1,1,1),
                    rank = c(3,3,3,3))

nodes3 <- data.frame(name = c("Hadley", "David", "Romain", "Julia"),
                    level = c(2,2,2,2),
                    rank = c(1,1,1,1))


edges <- data.frame(from = c(1, 1, 1, 2, 3, 3, 4, 4, 4),
                    to = c(2, 3, 4, 1, 1, 2, 1, 2, 3))


# create the tbl_graphs
tg <- tbl_graph(nodes = nodes, edges = edges)
tg_1 <- tbl_graph(nodes = nodes1, edges = edges)
tg_2 <- tbl_graph(nodes = nodes2, edges = edges)
tg_3 <- tbl_graph(nodes = nodes3, edges = edges)

# put into list
myList <- list(tg, tg_1, tg_2, tg_3)

为清楚起见,查看第一个列表元素如下所示:

> myList[1]
[[1]]
# A tbl_graph: 4 nodes and 9 edges
#
# A directed simple graph with 1 component
#
# Node Data: 4 × 3 (active)
  name   level  rank
  <chr>  <dbl> <dbl>
1 Hadley     1     1
2 David      1     1
3 Romain     1     1
4 Julia      1     1
#
# Edge Data: 9 × 2
   from    to
  <int> <int>
1     1     2
2     1     3
3     1     4
# … with 6 more rows

我们可以看到每个 object 都有一个名为 level 的变量和另一个名为 rank 的变量。我想做的是 return object 的列表索引,方法是 selecting levelrank 数字。因此,例如,如果我 select level = 1rank = 2,我的函数将 return 具有这些值的 object 的索引(在本例中为第 2 个列表元素)。我尝试的解决方案如下,但这是一个非常缓慢的过程......我想知道是否有更好的方法来实现我想要的?

我尝试的解决方案

在我的解决方案中,我首先将 tidygraph object 中的每一个都变成小标题,以使它们更易于操作。这就是为什么我的功能这么慢。在我的数据中,一个列表中最多可以包含 200,000 tidygraph object,因此遍历它们并将它们全部转换为 tibbles 是一个非常缓慢的过程。我是这样做的:

# seperating out the list to make it easier to manipulate
list_obj <- lapply(myList, function(x){
  edges <- tidygraph::activate(x, edges) %>% tibble::as_tibble()
  nodes <- tidygraph::activate(x, nodes) %>% tibble::as_tibble()
  return(list(edges = edges, nodes = nodes))
} )

然后这是我实际用来提取所选索引的函数 object:

# this function returns the tree index asked for by user
getTreeListNumber <- function(listObj, level, rank){
  
  res <- 0
  listNumber <- NA
  
  for(i in 1:length(listObj)){
    res <- level %in% listObj[[i]]$nodes$level && rank %in% listObj[[i]]$nodes$rank
    if(res == TRUE){
      listNumber <- i
    }
  }
  return(listNumber)
}

例如:

> getTreeListNumber(list_obj, level = 1, rank = 2)
[1] 2

通过 selecting 级别和排名,函数 return 列表中的 objects 索引。但是有没有更快的方法来达到这个结果呢?

你可以试试-

getTreeListNumber <- function(listObj, level, rank){
  which(sapply(myList, function(x) {
    nodes <- tidygraph::activate(x, nodes) %>% tibble::as_tibble() 
    all(nodes$level == level & nodes$rank == rank)
  }))
}

getTreeListNumber(myList, 1, 2)
#[1] 2