Zip-списки в R

В качестве ориентира я предпочитаю применять функции на элементах списка, используя lapply или * ply (от plyr), а не явно итерации через них. Однако это хорошо работает, когда мне приходится обрабатывать один список за раз. Когда функция принимает несколько аргументов, я обычно делаю цикл.

Мне было интересно, возможно ли иметь более чистую конструкцию, все еще функциональную по своей природе. Одним из возможных подходов может быть определение функции, аналогичной Python, zip (x, y), которая берет входные списки и возвращает список, i-ый элемент которого является списком (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

        ...

И вот пример с zipped (который может быть расширен до произвольных аргументов):

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

 ...

Ответы

Ответ 1

Я думаю, что вы ищете 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.

Ответ 2

Я думаю, вы могли бы сделать это с помощью того, что я называю "неявным циклом" (это имя не попадает полностью, но что угодно), принимая во внимание, что вы можете перебирать векторы внутри *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, поэтому мне жаль, если я пропустил вашу точку.)

Ответ 3

Я встретил подобную проблему сегодня. И после изучения использования func 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 
##    "牛"    "鸡"    "猪" 

КОНЕЦ.