背景
我正在查询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 NA和this 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 与每个步骤正在做什么,或者这是否是正确的方法。
答案 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")
>