4

I'm have a nested list I would like to convert to a dataframe.

iter1 <- list(item1 = 1, item2 = "a")
iter2 <- list(item1 = 1, item2 = "b")
All <- list(iter1 = iter1, iter2 = iter2)

df <- data.frame(t(sapply(All,c))) # Convert list to dataframe

But my problem is that df$iter1 returns a list instead of a dataframe, any idea ?

> class(df)
[1] "data.frame"

> df$item1
$iter1
[1] 1

$iter2
[1] 1

I have the same problem when converting with do.call : df <- data.frame(do.call(rbind, All)) but I can't figure out what is wrong.

Florent
  • 1,791
  • 22
  • 40
  • df$iter1 cannot return a data.frame! An item of a data.frame can be a vector or a list. By the way df is a dataframe but its items are lists not vectors. Suppose you want them to be vectors of numeric and character values respectively? – Serhat Cevikel Dec 08 '17 at 18:51

3 Answers3

3
temp = unique(unlist(lapply(All, names)))
mydf = setNames(object = data.frame(lapply(temp, function(nm)
    unlist(lapply(All, function(x) x[[nm]])))), nm = temp)

mydf
#      item1 item2
#iter1     1     a
#iter2     1     b

OR

do.call(rbind, lapply(All, data.frame))
#      item1 item2
#iter1     1     a
#iter2     1     b

OR

data.table::rbindlist(All, idcol = TRUE)
#     .id item1 item2
#1: iter1     1     a
#2: iter2     1     b
d.b
  • 32,245
  • 6
  • 36
  • 77
  • 1
    For the last one: That's the perfect way @d.b! And as.data.frame(data.table::rbindlist(All, idcol = TRUE)) converts it to a data frame if it is necessary. – Serhat Cevikel Dec 10 '17 at 10:24
1

Would lapply do what you want ?:

iter1 <- list(item1 = 1, item2 = "a")
iter2 <- list(item1 = 1, item2 = "b")
All <- list(iter1 = iter1, iter2 = iter2)

And then:

df <- as.data.frame(lapply(All, unlist))

> str(df)
'data.frame':   2 obs. of  2 variables:
 $ iter1: Factor w/ 2 levels "1","a": 1 2
 $ iter2: Factor w/ 2 levels "1","b": 1 2
user3375672
  • 3,728
  • 9
  • 41
  • 70
0

I think you want the first column to be a numeric vector as 1,1 and the second column to be a character vector as "a" and "b"?

How about this:

iter1 <- list(item1 = 1, item2 = "a")
iter2 <- list(item1 = 1, item2 = "b")
All <- list(iter1 = iter1, iter2 = iter2)

extract <- function(x, listx) sapply(listx, "[[", x)

df <- lapply(1:2, extract, All)
df <- as.data.frame(df, col.names = names(All), stringsAsFactors = F)
df

And if you want a one-liner:

df <- as.data.frame(lapply(1:2, function(x, listx) sapply(listx, "[[", x), All), col.names = names(All), stringsAsFactors = F)
df
Serhat Cevikel
  • 720
  • 3
  • 11
  • You have iter1, iter2 as both col and row names, but I guess they belong on rows only, while cols should have item1, item2. – Frank Dec 08 '17 at 20:30