如何通过 R 中的多个子列表 运行 一个函数?

How to run a function through multiple sublists in R?

我有一个名为 AllVotes 的复杂嵌套列表,您可以在此处(在 .rds 中)找到它:

https://github.com/JMcrocs/MEPVote/blob/master/FinalVotes.rds

我正在尝试收集所有 mepid,一个存储在子列表 AllVotes[[x]]$votes$'+'$groups 中的命名号码。感谢这里的前一个问题,我可以对一个列表([[1]] 列表)执行此操作,但我想对从 [[1]] 到 [[2336] 的嵌套列表的所有列表执行此操作].

#For the list [[1]]
Result = c(unlist( sapply ( names ( AllVotes[[1]]$votes$'+'$groups ), 
                   function(x) unlist( AllVotes[[1]]$votes$'+'$groups[[x]] ) ) ),
unlist( sapply ( names ( AllVotes[[1]]$votes$'-'$groups ), 
                   function(x) unlist( AllVotes[[1]]$votes$'-'$groups[[x]] ) )),
unlist( sapply ( names ( AllVotes[[1]]$votes$'0'$groups ), 
                   function(x) unlist( AllVotes[[1]]$votes$'0'$groups[[x]] ) )))

我该怎么做?提前致谢!

PS :如果问题不完美,我很抱歉我是编程新手两周(和 Overflow)。

您可以尝试使用循环并将结果保存在列表中,如下所示:

#Load
AllVotes <- readRDS('FinalVotes.rds')
#Loop
#Empty list
List <- list()
#For
for(i in 1:length(AllVotes))
{
  List[[i]] <- c(unlist( sapply ( names ( AllVotes[[i]]$votes$'+'$groups ), 
                                  function(x) unlist( AllVotes[[i]]$votes$'+'$groups[[x]] ) ) ),
                 unlist( sapply ( names ( AllVotes[[i]]$votes$'-'$groups ), 
                                  function(x) unlist( AllVotes[[i]]$votes$'-'$groups[[x]] ) )),
                 unlist( sapply ( names ( AllVotes[[i]]$votes$'0'$groups ), 
                                  function(x) unlist( AllVotes[[i]]$votes$'0'$groups[[x]] ) )))
}

你最终会得到 List 个有 2336 个元素。您可以使用 List[[15]] 等访问元素。然后你可以根据你的需要处理列表。

这是使用 lapply() 的策略。将您的代码转换为匿名函数,将 AllVotes[[1]] 替换为您的函数的参数,例如 list.

AllVotes <- readRDS('FinalVotes.rds')
out_list <- lapply(AllVotes, function(list) {
  c(unlist(sapply(names(list$votes$'+'$groups),
      function(x) unlist(list$votes$'+'$groups[[x]]))),        
      unlist(sapply(names(list$votes$'-'$groups), 
      function(x) unlist(list$votes$'-'$groups[[x]]))),
      unlist(sapply(names(list$votes$'0'$groups),
      function(x) unlist( list$votes$'0'$groups[[x]]))))
   })

我使用 rbenchmark 包对 Duck 的 for 循环答案进行基准测试,每个版本 运行 100 次。 benchmark() 的两个参数是我定义为两种方法包装器的函数,因此输出更容易解释。

library(rbenchmark)
benchmark(lapply_test(), loop_test())
           test replications elapsed relative user.self sys.self
1 lapply_test()          100  102.08    1.043    100.91     0.25  
2   loop_test()          100   97.86    1.000     96.87     0.15   

这两种方法在我的机器上看起来几乎相同,每次迭代大约需要 1 秒。循环版本稍微快一点,但差异很小,不同的机器可能 运行 lapply 版本更快。对于非常大的文件,其中一个可能会成为明显的赢家。此外,对于非常大的文件,lapply 版本很容易并行化。

您可以将代码简化为:

res <- lapply(AllVotes, function(x){
  unlist(lapply(c('+', '-', '0'), function(y){
    x$votes[[y]]$groups
  }))
})

给出与@Duck的答案相同的输出。

all.equal(res, List, check.attributes = F)
# [1] TRUE