【问题标题】:R list of lists to data.frameR列表到data.frame
【发布时间】:2015-04-16 12:25:07
【问题描述】:

我有一个列表列表,命名为listHolder,长度为 5。

listHolder 中的每个元素都是一个数字数据列表,大约有 160 个元素。

我需要将此列表列表转换为长度为 5 的 data.frame,每个元素都是一个包含 160 个左右元素的数字向量。

但是我尝试过的一切,从遍历列表列表到使用as.numeric(unlist(listHolder[[i]])) 转换每个元素,到

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

最终创建了一个长度为 160 左右的数据框,每个元素都是一个包含 5 个左右元素的数字向量。

我该如何做我想做的事?

尝试data.frame(matrix(unlist(totalKeywords), nrow=132, byrow=T)) 产生的结果与我想要的相反 - 160 个小项目,每个 5 个元素长。

【问题讨论】:

  • 试试do.call(rbind, listHolder)
  • R list to data frame 的可能重复项
  • 我想他想把每个 listHolder 项目都转成一列,所以应该是cbind 而不是rbind
  • 为什么不as.data.frame(listHolder)
  • 你能提供listHolder的样本数据吗?

标签: r dataframe


【解决方案1】:

正如前面提到的@dimitris_ps,答案可能是:

do.call(rbind, listHolder)

由于do.call自然会“剥离”1级“list of list”,得到一个list,而不是list的list。

之后,rbind可以处理列表中的元素并创建一个矩阵

【讨论】:

  • 这在“行”被命名为列表时非常有用,因为它保留了列表的名称(假设名称是一致的)
  • ...并且它不会更改像上面的“unlist”这样的数据类型。这就是答案!
  • 超级好用!但是,有没有办法将每个列表的编号/名称包含到最终数据框中?
【解决方案2】:

nrow 的值需要固定。我将您的代码修复如下:

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

【讨论】:

  • 我能做些什么来保留类型吗?按照这种方法,如果一列是POSIXct,它会将其转换为chr
  • 可以使用Reduce 保留类型(如我的回答)。
【解决方案3】:

这是我找到的最简单的解决方案。

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

【讨论】:

  • 唯一对我有用的方法。仍然没有像之前询问的那样保留POSIXct
【解决方案4】:

这实现了类似的结果,但更直观(至少对我而言)

#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

【讨论】:

  • 这不是列表列表。这是一个原子向量列表(强制转换为字符,因为您有不同的数据类型)。
【解决方案5】:

我不断提出这个问题,通常最终会根据我的需要调整当前的答案。

当前答案要么与变量类型混淆,要么不能很好地处理列表列表(注意复数)。

tl;dr:使用以下内容:

当 listHolder 中的每个元素都包含数据框的一列时,此方法有效

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

当 listHolder 中的每个元素都包含一行数据框时,此方法有效

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

最小的工作示例(列表元素是列)

以下代码提供 MWE 并查看其他答案。 #General Approach 是我推荐使用的。

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)

最小的工作示例(列表元素是行)

当列表中的每个元素都应该在数据框中保存一行时,应该使用此代码

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)

【讨论】:

    【解决方案6】:

    我认为这比以前的解决方案更容易:

    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
    

    【讨论】:

    • 也不是一个列表
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-22
    • 2016-05-15
    • 1970-01-01
    • 2015-02-15
    • 1970-01-01
    • 2012-02-13
    相关资源
    最近更新 更多