1

I want to turn a list of lists into a dataframe where each name(listoflists) is a different column name. It is a VERY big list so I want to do this in the most efficient way possible.

listoflists=list(c(1,2,3,4),c(5,6,7,8))
names(listoflists) <- c("col1", "col2")

What could I do to get the following results:

 print(df)
 col1     col2
  1        5
  2        6
  3        7
  4        8
 
mk2080
  • 872
  • 1
  • 8
  • 21

5 Answers5

2

We can wrap with data.frame

data.frame(listoflists)

-output

   col1 col2
1    1    5
2    2    6
3    3    7
4    4    8

In case the OP meant, it as a nested list, then unlist the inner list element by looping over the lapply and wrap with data.frame

data.frame(lapply(listoflists, unlist))

If it should be most efficient way, then setDT can be applied as well

library(data.table)
setDT(listoflists)

-output

> listoflists
   col1 col2
1:    1    5
2:    2    6
3:    3    7
4:    4    8
akrun
  • 874,273
  • 37
  • 540
  • 662
2

We can use !!! operator with tibble. Some examples:

library(tidyverse)

#first case
listoflists1=list(c(1,2,3,4),c(5,6,7,8)) %>%
  set_names(c("col1", "col2"))

tibble(!!!listoflists1)
#> # A tibble: 4 × 2
#>    col1  col2
#>   <dbl> <dbl>
#> 1     1     5
#> 2     2     6
#> 3     3     7
#> 4     4     8

#second case
listoflists2=list(list(1:4),list(5:8)) %>%
  set_names(c("col1", "col2"))

tibble(!!!listoflists2) %>%
  unnest(names(.))
#> # A tibble: 4 × 2
#>    col1  col2
#>   <int> <int>
#> 1     1     5
#> 2     2     6
#> 3     3     7
#> 4     4     8


#third case
listoflists3=list(list(1,2,3,4),list(5,6,7,8)) %>% set_names(c("col1", "col2"))

tibble(!!!listoflists3) %>%
  unnest(names(.))
#> # A tibble: 4 × 2
#>    col1  col2
#>   <dbl> <dbl>
#> 1     1     5
#> 2     2     6
#> 3     3     7
#> 4     4     8

#it is possible to use unnest without cols argument but it will throw a warning message.

Created on 2021-09-22 by the reprex package (v2.0.0)

jpdugo17
  • 6,816
  • 2
  • 11
  • 23
2

You can use list2DF.

list2DF(listoflists)
#  col1 col2
#1    1    5
#2    2    6
#3    3    7
#4    4    8

What will also work with a list of lists and not only with a list of numeric vectors.

x <- list(list(1,2,3,4),list(5,6,7,8))
names(x) <- c("col1", "col2")
list2DF(x)
#  col1 col2
#1    1    5
#2    2    6
#3    3    7
#4    4    8

If all list elements have the same length, an efficient but not recommended way might be:

class(listoflists) <- "data.frame"
attr(listoflists, "row.names") <- .set_row_names(length(listoflists[[1]]))
listoflists
#  col1 col2
#1    1    5
#2    2    6
#3    3    7
#4    4    8
GKi
  • 37,245
  • 2
  • 26
  • 48
1
library(dplyr)

bind_rows(listoflists)

# A tibble: 4 x 2
   col1  col2
  <dbl> <dbl>
1     1     5
2     2     6
3     3     7
4     4     8
Vinícius Félix
  • 8,448
  • 6
  • 16
  • 32
1

If you cannot use external libraries for some reason you can create a data.frame as follows:

out_df <- do.call(data.frame, listoflists)

If you want a faster implementation of data.frame you can use the data.table package instead.

library(data.table)
out_dt <- do.call(data.table, listoflists)

However the setDT proposed by @arkun should be faster in this case as it doesn't make a copy of the data.

N.B. My solutions work correctly only if your input is actually a list of vectors not when if it is a list of lists.

tarch
  • 381
  • 3
  • 3