在R中压缩列表

18
作为指南,我更喜欢使用lapply或*ply(来自plyr)在列表的元素上应用函数,而不是明确地迭代它们。但是,当我需要一次处理多个列表时,这种方法就不起作用了。当函数需要多个参数时,通常我会使用循环。
我想知道是否有更干净、仍然具有功能性质的构造方法。一种可能的方法是定义一个类似于Python中的zip(x,y)函数,它接受输入列表,并返回一个列表,其第i个元素是list(x, y),然后将该列表应用于函数。但我的问题是,我是否正在使用最清晰的方法。我不担心性能优化,而是关注代码的清晰度和优雅性。
下面是一个简单的示例:
        A <- as.list(0:9)
        B <- as.list(0:9)
        f <- function(x, y) x^2+y

        OUT <- list()
        for (n in 1:10) OUT[[n]] <- f(A[[n]], B[[n]])
        OUT
        [[1]]
        [1] 0

        [[2]]
        [1] 2

        ...

以下是被压缩的示例代码(可以用于任意参数):

zip <- function(x, y){
    stopifnot(length(x)==length(y))
    z <- list()
    for (i in seq_along(x)){
        z[[i]] <- list(x[[i]], y[[i]]) 
    }
    z
}
E <- zip(A, B)

lapply(E, function(x) f(x[[1]], x[[2]]))

[[1]]
[1] 0

[[2]]
[1] 2

 ...
3个回答

29

我认为你正在寻找 mapply 函数:

   ‘mapply’ is a multivariate version of ‘sapply’.  ‘mapply’ applies
     ‘FUN’ to the first elements of each ...  argument, the second
     elements, the third elements, and so on.  Arguments are recycled
     if necessary.

对于你的例子,使用mapply(f, A, B)


3
还有一个名为plyr的函数族,包括m*ply函数。 - Marek
2
而Map是一个围绕mapply的薄包装。 - hadley

4

今天我遇到过一个类似的问题。通过学习函数 mapply 的用法,现在我知道如何解决它了。

mapply 真是太棒了!

下面是一个例子:

en = c("cattle", "chicken", "pig")
zh = c("牛",      "鸡",      "猪")

dict <- new.env(hash = TRUE)
Add <- function(key, val) dict[[key]] <- val

mapply(Add, en, zh)
##  cattle chicken     pig 
##    "牛"    "鸡"    "猪"

1

我认为你可以使用我所谓的“隐式循环”来实现这一点(这个名称并不完全准确,但无论如何),考虑到你可以在*apply中循环向量:

OUT <- lapply(1:10, function(x) (A[[x]]^2 + B[[x]]))

或者

OUT <- lapply(1:10, function(x) f(A[[x]], B[[x]]))

请注意,您还可以使用vapply(或`sapply`)来管理输出(即,如果您不想要一个列表)。
(顺便说一句,我不明白您在zip函数中想要什么,所以如果我错过了您的重点,我很抱歉。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接