开发者

zipping lists in R

As a guideline I prefer apply functions on elements of a list using lapply or *ply (from plyr) rather than explicitly iterating through them. However, this works well when I have to process one list at a time. When the function takes multiple arguments, I usually do a cycle.

I was wondering if it's possible to have a cleaner construct, still functional in nature. One possible approach could be to define a function similar to Python, zip(x,y), which takes the input lists, and returns a list, whose i-th element is list(x, y), and then apply the function to this list. But my question is whether I am using the cleanest approach or not. I am not worried about performance optimization, but rather clarity/elegance.

Below is the naive example.

        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

        ...

And here is the zipped example (which could be extended to arbitrary arguments):

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

 ...


I think you're looking for 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.

For your example, use mapply(f, A, B)


I came across a similar problem today. And after learning the usage of the func mapply, I know how to solve it now.

mapply is so cool!!

Here is an examples:

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 
##    "牛"    "鸡"    "猪"


I think you could do this with what I call an 'implicit loop' (this name does not hit it fully, but whatever), taking into account that you can loop over vectors within *apply:

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

or

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

Note that you then could also use vapply (or 'sapply`) for output managing (i.e. if you don't want a list).

(by the way, I am not getting what you want with the zip function, so I am sorry, if I missed your point.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜