Background
I'm querying a mongodb database to find a document:
library(rmongodb)
...
res <- mongo.find.one(m, n, q, f) # <~~ returns BSON
res <- mongo.bson.to.list(res) # <~~ converts BSON to list
I'm then using this answer to try and convert it to a data frame
df <- as.data.frame(t(sapply(res[[1]], '[', seq(max(sapply(res[[1]],length))))))
However, this gives me a data frame of lists (subsetted here for convenience):
data
> 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
Issue
I would like to library(reshape2); melt
and then plot this data using ggplot2
, but as expected I 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
How can I convert this data to a 'standard' data frame (i.e. not a data frame of lists?), or melt
it as is?
Update
I hadn't properly considered the NULL
s in the data. Using a combination of a comment in this question - replacing NULL with NA and this answer - Convert List to DF with NULLs I came up with
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
This replaces the NULL
s with NA
s and allows me to melt
the data. However, I'm still not fully au fait with what each step is doing yet, or whether this is the right approach.