1

I have a list like so:

lst <-
list(structure(c("1", "[19]"), .Dim = 1:2), structure("1", .Dim = c(1L, 
1L)), structure(c("1", "[41]"), .Dim = 1:2), structure(c("1", 
"[55]"), .Dim = 1:2), structure(c("1", "[56]"), .Dim = 1:2), 
    structure(c("1", "[84]"), .Dim = 1:2))

How do I convert this into a tibble so that:

rslt <-
tibble(batch=c(1,1,1,1,1,1), id=c("[19]","","[41]","[55]","[56]","[84]"))

# A tibble: 6 x 2
  batch    id
  <dbl> <chr>
1     1  [19]
2     1      
3     1  [41]
4     1  [55]
5     1  [56]
6     1  [84]
Sati
  • 716
  • 6
  • 27
  • Try `library(tidyverse);lst %>% map_df(~as.data.frame(.))` – akrun Nov 10 '17 at 10:16
  • It works, but I got the following warning messages: `1: In bind_rows_(x, .id) : Unequal factor levels: coercing to character 2: In bind_rows_(x, .id) : binding character and factor vector, coercing into character vector 3: In bind_rows_(x, .id) : binding character and factor vector, coercing into character vector...` – Sati Nov 10 '17 at 10:24
  • 1
    I forgot to add the `stringsAsFactors=FALSE` i.e. `lst %>% map_df(~as.data.frame(., stringsAsFactors=FALSE))` – akrun Nov 10 '17 at 10:24
  • Can you explain how it works? – Sati Nov 10 '17 at 10:27
  • 1
    I posted a solution below with the explanation – akrun Nov 10 '17 at 10:32
  • 1
    FYI, the list you have here is not nested – Sotos Nov 10 '17 at 10:44

2 Answers2

3

We loop through the lst and convert it to data.frame as it is a matrix. Normally, using do.call(rbind, lst) should work if the dimensions were the same. But, here it is not the same. Using the map_dfr from purrr, we loop through each lst element, apply the function as.data.frame to convert it to data.frame and at the same time, we get a single dataset as we are using map_dfr

map_dfr() and map_dfc() return data frames created by row-binding and column-binding respectively. They require dplyr to be installed.

library(purrr)
map_dfr(lst, ~as.data.frame(., stringsAsFactors=FALSE))

Note: It returns NA for elements not present and it is better than having blank elements

akrun
  • 874,273
  • 37
  • 540
  • 662
  • @Sotos I think it is slightly different as it is a `list` of `vector`s – akrun Nov 10 '17 at 10:45
  • what does the squiggle `~` in `~as.data.frame` do? – Sati Nov 10 '17 at 14:31
  • Instead of using the pipe `%>%`, why can't I simply replace the `(.)` with `lst` like so? `map_df(~as.data.frame(lst))` – Sati Nov 10 '17 at 14:35
  • 1
    @Sati It won't work, because `map_df` needs a `.f` and `.x` which is the function and the object. i.e `map_dfr(.x, .f, ..., .id = NULL)` With only `map_df(~as.data.frame(lst))` there is only .`.f` – akrun Nov 10 '17 at 15:29
3

There is also a very convenient function in plyr package that can easily handle that,

plyr::rbind.fill(lapply(lst, as.data.frame))

#  V1   V2
#1  1 [19]
#2  1 <NA>
#3  1 [41]
#4  1 [55]
#5  1 [56]
#6  1 [84]
Sotos
  • 51,121
  • 6
  • 32
  • 66