Search code examples
rlistdata.tablerbind

using rbindlists for nested lists in R


I have a nested list as showed below. This is an simplified example, my original data has many hundres of items.

mtcars
mtcars <- mtcars[1:15,]
mtcars <- as.data.table(mtcars)

iris
iris <- iris[1:10,]
iris <- as.data.table(iris)

result <- vector("list", 3)
names <- c("Item 1", "Item 2", "Item 3")
names(result) <- names

testList1 <- list(mtcars, iris)

rm(result)
result <- list(Item1 = list(cars = mtcars,
                            flowers = iris),
               Item2 = list(cars = mtcars,
                            flowers = iris),
               Item3 = list(cars = mtcars,
                            flowers = iris))

which i want to summarise results, such that I become two data.tables : one for flowers and the other one fro cars.

I tried using result <- rbindlist(result, use.names = TRUE, fill = TRUE) but that results in an error.

The desired outcome is:

testList1 <- list(iris, iris, iris)
flowers <- rbindlist(testList1, use.names = TRUE, fill = TRUE)
flowers

testList1 <- list(mtcars, mtcars, mtcars)
cars <- rbindlist(testList1, use.names = TRUE, fill = TRUE)
cars

How can i bind the nested list, considering that the original results is much larger than the example?


Solution

  • You can use purrr's transpose and bind_rows from dplyr.

    library(purrr)
    transpose(result) %>% map(dplyr::bind_rows)
    
    #$cars
    #     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
    # 1: 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
    # 2: 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
    # 3: 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
    # 4: 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
    # 5: 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
    #...
    
    #$flowers
    #    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
    # 1:          5.1         3.5          1.4         0.2  setosa
    # 2:          4.9         3.0          1.4         0.2  setosa
    # 3:          4.7         3.2          1.3         0.2  setosa
    # 4:          4.6         3.1          1.5         0.2  setosa
    # 5:          5.0         3.6          1.4         0.2  setosa
    #...
    

    We can add an 'id' column :

    transpose(result) %>% map(dplyr::bind_rows, .id = "id")
    
    #$cars
    #     mpg cyl  disp  hp drat    wt  qsec vs am gear carb    id
    # 1: 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 Item1
    # 2: 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 Item1
    # 3: 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 Item1
    #...
    #...
    #43: 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3 Item3
    #44: 15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3 Item3
    #45: 10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4 Item3
    #     mpg cyl  disp  hp drat    wt  qsec vs am gear carb    id
    
    #$flowers
    #    Sepal.Length Sepal.Width Petal.Length Petal.Width Species    id
    # 1:          5.1         3.5          1.4         0.2  setosa Item1
    # 2:          4.9         3.0          1.4         0.2  setosa Item1
    # 3:          4.7         3.2          1.3         0.2  setosa Item1
    #...
    #29:          4.4         2.9          1.4         0.2  setosa Item3
    #30:          4.9         3.1          1.5         0.1  setosa Item3
    #    Sepal.Length Sepal.Width Petal.Length Petal.Width Species    id