如何通过 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
我有一个名为 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