将函数应用于列表中的列表

applying a function to lists within a list

我想将函数应用到列表中的列表。二级列表由任意数量的字符串组成(这就是为什么,在我遗漏一些东西的情况下,列表中的列表数据结构是最合适的)。我想知道最有效的方法是什么。这是一个简单的例子,它通过循环完成我想要的:

#sample data
set.seed(12345)
mylist <- list()
mylist[[1]] <- list(sample(letters,3),sample(letters,4),sample(letters,5))
mylist[[2]] <- list(sample(letters,4),sample(letters,5))
mylist[[3]] <- list(sample(letters,5),sample(letters,3),sample(letters,4),sample(letters,2)

#working loop example
result <- list()
for(i in 1:length(mylist)){
  result[[i]] <- lapply(mylist[[i]],function(x,l) 0  + (l %in% x),l=letters)
}

有没有一种简单的方法可以将这个循环变成单行解决方案?

更广泛的背景是我想进一步减少 result 中的数据,例如(在这个简单的例子中)通过加起来得到每个字母在 i 上出现的次数,或 mylist 的原始维度。所以最终目标是这样的:

final.result <- lapply(result,Reduce,f='+')

因此,另一种方法可能是简单地将函数应用于 unlist(mylist),然后以某种方式将 i 信息恢复到生成的数据结构中……这对我来说似乎更复杂,但我愿意接受建议。

您可以使用带参数 how='list' 的递归 ?rapply 来保持列表结构,然后换行 Reduce 以获得最终结果:

lapply(rapply(mylist,function(x) letters %in% x + 0, how='list'), Reduce, f='+')

正如 Beauvel 上校所指出的,您的函数可以使用 letters 来缩短。

对于你的第一个结果,你可以这样做:

result <- lapply(mylist, function(x){lapply(x, function(y) {+(letters %in% y)})})

要获得最终结果,您可以这样做:

final.result <- lapply(mylist, function(x){colSums(do.call("rbind",lapply(x, function(y) {+(letters %in% y)})))})

或者,使用 result:

lapply(result, function(x){colSums(do.call("rbind", x))})

两者都给出:

final.result
#[[1]]
# [1] 1 0 0 2 0 0 0 1 0 0 0 1 0 1 0 0 0 0 2 0 0 1 0 2 0 1
#
#[[2]]
# [1] 1 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1
#
#[[3]]
# [1] 1 0 0 0 1 1 0 0 1 1 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 1