r - 列表的数据帧到数据帧中

时间:2015-03-22 11:00:18

标签: r dataframe

背景

我正在查询mongodb数据库以查找文档:

library(rmongodb)
...
res <- mongo.find.one(m, n, q, f)  # <~~ returns BSON 
res <- mongo.bson.to.list(res)     # <~~ converts BSON to list

然后我使用this answer尝试将其转换为数据框

df <- as.data.frame(t(sapply(res[[1]], '[', seq(max(sapply(res[[1]],length))))))

然而,这给了我一个列表数据框(为方便起见,这里是子集):

数据

> dput(df)
structure(list(horse_id = list(17643L, 4997L, 20047L, 9914L, 
17086L, 12462L, 18490L, 17642L, 26545L, 27603L, 14635L, 13811L, 
27719L, 31585L, 9644L), start_1400m = list(14.76, 14.3, 14.48, 
15.11, 14.65, 14.63, 14.85, 14.54, 14.93, 14.5, 14.78, NULL, 
NULL, NULL, NULL), `1400m_1200m` = list(12.96, 12.47, 12.47, 
13.02, 12.65, 12.92, 13.11, 12.37, 13, 12.84, 12.79, NULL, 
NULL, NULL, NULL)), .Names = c("horse_id", "start_1400m", 
"1400m_1200m"), row.names = c(NA, 15L), class = "data.frame")

> head(df)
    horse_id start_1400m 1400m_1200m
1    17643       14.76       12.96
2     4997        14.3       12.47
3    20047       14.48       12.47
4     9914       15.11       13.02
5    17086       14.65       12.65
6    12462       14.63       12.92

问题

我想library(reshape2); melt,然后使用ggplot2绘制此数据,但正如预期的那样can't melt data.frames with non-atomic columns

> melt(df, id.vars=c("horse_id"))
Error: Can't melt data.frames with non-atomic 'measure' columns

如何将此数据转换为“标准”数据框(即不是列表的数据框?),或melt原样?

更新

我没有正确考虑数据中的NULL。使用a comment in this question - replacing NULL with NAthis answer - Convert List to DF with NULLs的组合,我想出了

d <- as.data.frame(do.call("rbind", df))

library(plyr)
d <- rbind.fill(lapply(d, function(f) {
  data.frame(Filter(Negate(is.null), f))
}))

names(d) <- sub("X","",names(d))      #<~~ clean the names
d <- melt(d, id.vars=c("horse_id"))   #<~~ melt for use in ggplot2

这会将NULL替换为NA s,并允许我melt数据。但是,我仍然没有完全 au fait 与每个步骤正在做什么,或者这是否是正确的方法。

1 个答案:

答案 0 :(得分:-1)

从向量或列表创建的data.frames在dput()输出中将这些对象表示为列表是正常的,这通常不是问题,因为它仍然作为data.frame工作。

例如:

> a = list(1, 2, 3)
> b = list(4, 5, 6)
> df = data.frame(a)
> df = rbind(b, df)
> df
   X1 X2 X3
1   4  5  6
2   1  2  3
> s = sum(df[,2])
> s
[1] 7
> str(df)
'data.frame':   2 obs. of  3 variables:
 $ X1: num  4 1
 $ X2: num  5 2
 $ X3: num  6 3
> dput(df)
structure(list(X1 = c(4, 1), X2 = c(5, 2), X3 = c(6, 3)), .Names = c("X1", 
"X2", "X3"), row.names = 1:2, class = "data.frame")
>