2015-03-22 2 views
1

фонг - кадр данных списков в кадр данных

Я запрашивая базу данных 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)))))) 

Однако, это дает мне кадр данных списков (subsetted здесь для удобства):

данные

> 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 это как?

Update

я не учёл должным образом 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 с и позволяет мне melt данных. Тем не менее, я все еще не полностью au fait с тем, что делает каждый шаг, или же это правильный подход.

+1

Что такое желаемый результат? Что насчет 'melt (lapply (df, unlist))'? – A5C1D2H2I1M1N2O1R2T1

+0

Определенно не используйте sapply, так как он пытается преобразовать свой вывод в список. Согласно комментарию в вашей ссылке, было бы лучше использовать vapply, но я бы согласился применить и обернуть его с помощью unlist, чтобы убедиться, что вывод не является списком. Возможно, мне понадобится переместить unlist на уровень глубже, если вы все равно получите X списков. –

+0

@AnandaMahto - спасибо за предложение, но этот метод теряет связь между значениями 'horse_id' и' start_1400m', '1400m_1200m' (хотя некоторые являются' NULL'), не так ли? – tospig

ответ

-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") 
> 
+0

Действительно ли вы пытались использовать 'str (df)' для данных, предоставленных OP. Он полностью отличается от вашего. –

+0

OP - я думаю, вы имеете в виду tospig - не предоставляли данные для тестирования. Тем не менее, tospig показал «mongo.bson.to.list (res)», который указывает возможность конвертировать все, что попадает в список. Если это сделано, нет причин, по которым он не должен работать, как я показал. Однако, если нет, тогда его нужно будет преобразовать в правильный список, и это должно быть простым делом его расщепления, –

+0

OP * сделал * предоставить набор данных. Попробуйте прочитать вопрос.Решение @Anandas решит эту проблему, беря данные * как есть *. –

Смежные вопросы