поэлементная комбинация двух списков в R

Скажем, у меня есть два списка:

list.a <- as.list(c("a", "b", "c"))

list.b <- as.list(c("d", "e", "f"))

Я хотел бы рекурсивно объединить эти списки, чтобы результатом был список объединенных элементов в виде вектора, подобного следующему:

[[1]]
[1] a d

[[2]]
[1] a e

[[3]]
[1] a f

[[4]]
[1] b d

и так далее. Я чувствую, что мне не хватает чего-то относительно простого здесь. Любая помощь?

Ваше здоровье.


person sinclairjesse    schedule 22.10.2012    source источник
comment
expand.grid(list.a, list.b) даст вам то, что вы хотите, в структуре data.frame, которая, возможно, более полезна.   -  person Matthew Plourde    schedule 22.10.2012
comment
Мне нужен результирующий список для do.call, чтобы сгенерировать серию графиков, где x — элементы list.a, а y — элементы list.b (т. е. a[1], b[1] ; а[1], b[2]; ...; а[n], b[k]).   -  person sinclairjesse    schedule 22.10.2012
comment
см. также связанные: stackoverflow.com/questions/ 6515134/   -  person Ben Bolker    schedule 23.10.2012


Ответы (6)


expand.grid(list.a, list.b) дает желаемый результат в виде data.frame. Это, как правило, наиболее удобный формат для работы с данными в R. Однако вы можете получить точную структуру, которую вы запрашиваете (сохранив порядок), с помощью вызова apply и lapply:

result.df <- expand.grid(list.a, list.b)
result.list <- lapply(apply(result.df, 1, identity), unlist)

Если вы хотите, чтобы этот список упорядочен по первому элементу:

result.list <- result.list[order(sapply(result.list, head, 1))]
person Matthew Plourde    schedule 22.10.2012
comment
Это не воспроизводимо. Что такое к? - person sinclairjesse; 22.10.2012
comment
+1 - Приятно видеть, что expand.grid() работает со списками, а также с более простыми векторами. - person Josh O'Brien; 22.10.2012
comment
Сладкий. Спасибо! Мне кажется странным, что нет встроенной функции для рекурсивного объединения списков. Я один здесь? - person sinclairjesse; 22.10.2012
comment
Это не работает, если каждый список содержит несколько подэлементов для каждого элемента. Например, если бы вместо list.a <- list(c("a","b","c"),c("x","y","z")) было list.a, то не было бы желаемого результата... - person theforestecologist; 21.07.2017

Вы хотите mapply (если под "рекурсивно" вы подразумеваете "параллельно"):

mapply(c, list.a, list.b, SIMPLIFY=FALSE)

Или, может быть, это больше, что вы хотите:

unlist(lapply(list.a, function(a) lapply(list.b, function (b) c(a, b))), recursive=FALSE)
person dholstius    schedule 25.05.2013

Удивлен, что никто не упомянул этот простой лайнер:

as.list(outer(list.a,list.b, paste))

[[1]]
[1] "a d"

[[2]]
[1] "b d"

[[3]]
[1] "c d"

[[4]]
[1] "a e"
person Community    schedule 27.05.2018
comment
Кажется, это заставляет ввод в строки. Я попробовал это с целыми числами, x <- c(1, 2, 3) и y <- c(4, 5, 6), и он превращает все в строки. - person Steven C. Howell; 19.07.2018

Это дает вам то, что вы ищете:

unlist(lapply(list.a, function(X) {
    lapply(list.b, function(Y) {
        c(X, Y)
    })
}), recursive=FALSE)
person Josh O'Brien    schedule 22.10.2012

Вот функция, в которую вы можете передавать списки для расширения

expand.list <- function(...){
   lapply(as.data.frame(t((expand.grid(...)))),c, recursive = TRUE, use.names = FALSE)}

 expand.list(list.a, list.b)
person mnel    schedule 22.10.2012

Вот несколько грубый подход, который, учитывая, что они имеют одинаковые размеры, рекурсивно добавляет list.b к list.a, используя функцию добавления.

# CREATE LIST OBJECTS 
  list.a <- as.list(c("a", "b", "c"))
  list.b <- as.list(c("d", "e", "f"))

# CREATE AN EMPTY LIST TO POPULATE      
list.ab <- list()

# DOUBLE LOOP TO CREATE RECURSIVE COMBINATIONS USING append
    ct=0    
      for( i in 1:length(list.a) ) {    
        for (j in 1:length(list.b) ) {
          ct=ct+1
           list.ab[[ct]] <- append(list.a[[i]], list.b[[j]])     
         } 
       }

# PRINT RESULTS
list.ab
person Jeffrey Evans    schedule 22.10.2012