Search code examples
rlistmatrixcbind

How to use cbind on matrices in one list and place them in another (r)


I'm trying to join matrices stored in nested lists and place them in a new list. For example, if I have a list of fruit, I would like to take various matrices stored under Kiwi, and join them together as one matrix in a new list.

This will generate something that looks like my data:

#Define some important things
Fruits = c('Mango', 'Kiwi')
Attr = c('Size', 'Shape')

#generate empty lists
MyFruitList <- lapply(Fruits, function(q) {
  EmptySublist <- (setNames(vector("list", length(Fruits)), Attr))
})
names(MyFruitList) <- Fruits

#Full lists with example matrices
MyFruitList[['Mango']][['Size']] <- matrix(c(3,5,7,2), nrow=2, ncol=2)
MyFruitList[['Mango']][['Shape']] <- matrix(c(3,6,7,5), nrow=2, ncol=2)

MyFruitList[['Kiwi']][['Size']] <- matrix(c(1,3,4,2), nrow=2, ncol=2)
MyFruitList[['Kiwi']][['Shape']] <- matrix(c(2,4,5,1), nrow=2, ncol=2)

And here is what I have been trying to use to move the matrices stored under Kiwi and Mango into a new list.

#Obviously this doesn't actually work
MyFruitListAsRows <- lapply(Fruits, function(i) {
  MyFruitListAsRows <- matrix(cbind(paste0(MyFruitList[i]))) 
})
names(MyFruitListAsRows) <- paste0(Fruits, "Row")

Ideally I should end up with a list called MyFruitsAsRows which contains 2, 4 by 2 matrices named Kiwi and Mango, containing their respective Size and Shape data from the original MyFruitList list.

e.g. For Mango it would look like this:

     [,1] [,2] [,3] [,4] 
[1,]    3    7   3    7
[2,]    5    2   6    5

(Sorry that the numbers are overly similar, that was not well planned and might make it hard at first to recognise where I'd like my numbers to go)

Having been constructed from this:

$Size
     [,1] [,2]
[1,]    3    7
[2,]    5    2

$Shape
     [,1] [,2]
[1,]    3    7
[2,]    6    5

Edit: I have tried to adapt the advice of Ronak Shah and done the following:

library(tidyverse)

MyFruitListAsRows <- map(MyFruitList[i], bind_cols)

but running either,

MyFruitListAsRows[['KiwiRow']]
MyFruitListAsRows[['MangoRow']]

Produces:

I get Error in x[i, , drop = FALSE] : subscript out of bounds

If I try to get RStudio to show me what's in either of my new lists in a window, RStudio encounters a fatal error and crashes.


Solution

  • We can use base R to loop over each MyFruitList and cbind them with do.call

    lapply(MyFruitList, function(x) do.call(cbind, x))
    
    #$Mango
    #     [,1] [,2] [,3] [,4]
    #[1,]    3    7    3    7
    #[2,]    5    2    6    5
    
    #$Kiwi
    #     [,1] [,2] [,3] [,4]
    #[1,]    1    4    2    5
    #[2,]    3    2    4    1
    

    You can also use cbind.data.frame here.


    Using tidyverse we can map over each list and then cbind

    library(tidyverse)
    map(MyFruitList, cbind.data.frame)
    
    #$Mango
    #  Size.1 Size.2 Shape.1 Shape.2
    #1      3      7       3       7
    #2      5      2       6       5
    
    #$Kiwi
    #  Size.1 Size.2 Shape.1 Shape.2
    #1      1      4       2       5
    #2      3      2       4       1