17

Consider the following list of lists:

lst = list(list(c(1,2), c(3,4)),list(c(5,6), c(7,8)),list(c(9,10), c(11,12)))

The list lst contains three lists, each list containing two vectors as elements. I would like to combine the elements of the underlying lists by index. In other words, I would like to merge vector 1 from list 1 with that of list 2 and list 3, and vector 2 from list 1 with that of list 2 and list 3, etc...

This is the result I am looking to achieve:

res = list(c(1,2,5,6,9,10), c(3,4,7,8,11,12))

I know that this can be achieved as follows in case of two separate lists:

mapply(c, lst1, lst2)

However, I am not sure how to replicate the same logic using a list of lists.

Any efficient way to achieve that? Please keep in mind that in reality, lst is a list of 5000 lists, and each underlying list contains a large number of vectors.

Thanks!

Mayou
  • 8,498
  • 16
  • 59
  • 98
  • Maybe `sapply(1:length(lst) function(j)list[[j]][[1]])` and similarly but ending in `[[2]]` will suffice? – Carl Witthoft Oct 21 '13 at 17:05
  • 1
    The problem is that in reality, each of the individual lists contain wayyy more vectors, and not only 2. It wouldn't be efficient/feasible to write the same equation indefinitely for each vector. – Mayou Oct 21 '13 at 17:07

3 Answers3

22

You can do:

do.call(Map, c(c, lst))
flodel
  • 87,577
  • 21
  • 185
  • 223
  • Nice. I guess ours are basically identical, but `Map` sure is cleaner. – joran Oct 21 '13 at 17:08
  • I am not sure why I am getting the following error when applying it to my practical problem: `Error in match.fun(f) : '100' is not a function, character or symbol` ... – Mayou Oct 21 '13 at 17:08
  • maybe you have a variable `c` thar has a value of `100`. You could replace `c` above by `base::c`. – flodel Oct 21 '13 at 17:09
  • Great thanks. Would this work if the underlying lists have elements as matrices, and not vectors? – Mayou Oct 21 '13 at 17:10
  • depends what you want to do with matrices, you might want to replace `c` by `cbind` or `rbind`. – flodel Oct 21 '13 at 17:11
  • I have never worked with Map before. Could you please show me how you would adapt it to achieve that? I have tried changing to `cbind` but it is not doing the trick.. – Mayou Oct 21 '13 at 17:13
  • @Mariam - in that case you may be better off learning what `cbind` and `c` and `mapply` actually do. It sounds like you're a bit new to the paradigms under which `R` works. – Carl Witthoft Oct 21 '13 at 17:17
  • 1
    `Map` is like `mapply` with `SIMPLIFY = FALSE`. I was suggesting you try `do.call(Map, c(cbind, lst))` but it's hard to tell exactly without an example. – flodel Oct 21 '13 at 17:18
  • @CarlWitthoft I actually am very familiar with those methods, and I have modified the above formula using cbind and couldn't achieve the proper result – Mayou Oct 21 '13 at 17:18
7

You're on the right track:

do.call(function(...) mapply(c,...,SIMPLIFY = FALSE),args = lst)
[[1]]
[1]  1  2  5  6  9 10

[[2]]
[1]  3  4  7  8 11 12
joran
  • 169,992
  • 32
  • 429
  • 468
  • 1
    Great thanks! How about if each underlying list contains matrices and not vector, and I would want to merge the matrices next to each others. How can I adapt your formula to doing that? – Mayou Oct 21 '13 at 17:15
1

I was looking for something along the lines of the OP's question... but with a list of data frames instead of vectors. In that case, slightly modifying @joran's answer above gives the desired result. Consider:

mylist <- 
  lapply(1:2, function(y){
    df1 <- data.frame(a=y, b=y^2, c=y^3)
    df2 <- data.frame(d=y, e=y+1)
    return(list(df1=df1, df2=df2))
    }) 

You can then re-combine the sub-list elements into separate data frames based on their common indexes:

mylist2 <- do.call(function(...) Map("rbind", ...), mylist)
Grant
  • 1,536
  • 13
  • 25