简体   繁体   中英

R list of lists to data.frame

I've got a list of lists, call it listHolder , which has length 5.

Every element in listHolder is a list of numeric data, with 160 or so elements.

I need to turn this list of lists into a data.frame of length 5, with each element being a numeric vector with 160 or so elements.

But everything I've tried, from iterating through the list of lists and turning each element with as.numeric(unlist(listHolder[[i]])) , to

data.frame(matrix(unlist(listHolder), nrow = length(totalKeywords), byrow = T))

ends up creating a data frame of length 160 or so, with each element being a numeric vector with 5 or so elements.

How do I do what I want?

Attempting data.frame(matrix(unlist(totalKeywords), nrow=132, byrow=T)) yields the opposite of what I want - 160 small items each 5 elements long.

AS @dimitris_ps mentioned earlier, the answer could be:

do.call(rbind, listHolder)

Since do.call naturally "strips" 1 level of the "list of list", obtaining a list, not a list of lists.

After that, rbind can handle the elements on the list and create a matrix .

The value of nrow needs to be fixed. I fixed your code as follows:

dd  <-  as.data.frame(matrix(unlist(listHolder), nrow=length(unlist(listHolder[1]))))

This achieves a similar result, but is more intuitive (to me at least)

#Generate fake data 
listoflists=list(c(1,'a',3,4),c(5,'b',6,7))

#Convert to a dataframe, transpose, and convert the resulting matrix back to a dataframe
df= as.data.frame(t(as.data.frame(listoflists)))

#Strip out the rownames if desired
rownames(df)<-NULL

#Show result
df

This is the easiest solution I've found.

library(jsonlite)
library(purrr)
library(data.table)

dt_list <- map(list_of_lists, as.data.table)
dt <- rbindlist(dt_list, fill = TRUE, idcol = T)

dt

I keep coming to this question and usually end up adapting the current answers to my need.

Current answers either mess up with types of variables, or do not handle well proper list of lists (note the plural).

tl;dr: use the following:

This works when each element in listHolder contains a column of the dataframe

df <- data.frame(lapply(listHolder, function(x) Reduce(c, x)))

This works when each element in listHolder contains a row of the dataframe

df <- do.call(rbind, lapply(listHolder, data.frame))

Minimal Working Example (list elements are columns)

The following code provides a MWE and reviews other answers. The #General Approach is what I would recommend to use.

listHolder <- list(
  A = rep(list(1, 2), 80),
  B = rep(c(3, 4), 80),
  C = rep(c("a", "b"), 80),
  D = rep(list("c", "d"), 80),
  E = rep(as.POSIXct(10485849600, origin = "1582-10-14", tz = "GMT"), 160)
)


# @Noha's Answer
data1  <-  as.data.frame(matrix(unlist(listHolder), nrow=length(unlist(listHolder[1]))))
# Try this (mess up with types)
str(data1)

# @Camilo's Answer
data2 <- data.frame(do.call(cbind, listHolder))
# Try this (each column becomes a list)
str(data2)

# General Approach
data3 <- data.frame(lapply(listHolder, function(x) Reduce(c, x)))
str(data3)

Minimal Working Example (list elements are rows)

This code should be used when each element in the list is supposed to hold a row in the dataframe

listHolder <- list(
  row1 = list(name = "foo", surname = "bar", age = 90),
  row2 = list(name = "foo", surname = "foo", age = 29),
  row3 = list(name = "bar", surname = "foo", age = 45),
  row4 = list(name = "bar", surname = "bar", age = 10)
)

# A simple rbind won't work (each column is still a list)
data1 <- do.call(rbind, listHolder)
str(data1)

# General Approach (now it's better)
data2 <- do.call(rbind, lapply(listHolder, data.frame))
str(data2)

I think this is easier than the previous solutions:

mydf = data.frame(x1 = c('a', 'b', 'c'))
mylist = list(c(4, 5), c(4, 5), c(4, 5))
mydf$x2 = mylist
print(mydf)
  x1   x2
1  a 4, 5
2  b 4, 5
3  c 4, 5

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM