Ответ 1
Вы можете использовать Reduce
, одно решение для линейки:
Reduce(merge,mylist)
names age score country
1 John 21 22 US
2 Sam 22 25 SA
У меня есть список, содержащий фреймы данных как его элементы в R.
Пример:
df1 <- data.frame("names"=c("John","Sam","Dave"),"age"=c(21,22,25))
df2 <- data.frame("names"=c("John","Sam"),"score"=c(22,25))
df3 <- data.frame("names"=c("John","Sam","Dave"),"country"=c("US","SA","NZ"))
mylist <- list(df1,df2,df3)
Можно ли объединить все элементы mylist вместе без использования цикла?
Мой желаемый результат для этого примера:
names age score country
1 John 21 22 US
2 Sam 22 25 SA
Список в этом примере содержит только три элемента; однако я ищу решение, которое может обрабатывать произвольное количество элементов.
Вы можете использовать Reduce
, одно решение для линейки:
Reduce(merge,mylist)
names age score country
1 John 21 22 US
2 Sam 22 25 SA
Быстрый и грязный пример:
merge(merge(df1, df2),df3)
EDIT - очень похожий вопрос здесь: Одновременно слияние нескольких файлов данных в списке
решение:
merged.data.frame = Reduce(function(...) merge(..., all=F), my.list)
Отказ от ответственности - все, что я изменил из ответа @Charles, заключалось в том, чтобы сделать merge(..., all=F)
, а не T
- таким образом он дает желаемый результат.
Просто, чтобы показать, что это может быть сделано другим способом...
mymerge <- function(mylist) {
names(mylist) <- sapply(mylist, function(x) names(x)[2])
ns <- unique(unlist(lapply(mylist, function(x) levels(x$names))))
as.data.frame(c(list(names=ns), lapply(mylist, function(x)
{x[match(ns, x$names),2]})))
}
> mymerge(mylist)
names age score country
1 Dave 25 NA NZ
2 John 21 22 US
3 Sam 22 25 SA
Можно легко адаптироваться для удаления строк с отсутствующими значениями или, возможно, просто удалить их с помощью complete.cases
.
Чтобы показать, что это быстрее, мы составим больший набор данных; 100 переменных и 25 имен.
set.seed(5)
vs <- paste0("V", 1:100)
mylist <- lapply(vs, function(v) {
x <- data.frame(names=LETTERS[1:25], round(runif(25, 0,100)))
names(x)[2] <- v
x
})
> microbenchmark(Reduce(merge, mylist), myf(mylist))
Unit: milliseconds
expr min lq median uq max
1 myf(mylist) 12.81371 13.19746 13.36571 14.40093 33.90468
2 Reduce(merge, mylist) 199.23714 206.28608 207.30247 208.44939 226.05980
Вы пробовали эту функцию?
http://rss.acs.unt.edu/Rdoc/library/gtools/html/smartbind.html
library(gtools)
df1 <- data.frame(list(A=1:10), B=LETTERS[1:10], C=rnorm(10) )
df2 <- data.frame(A=11:20, D=rnorm(10), E=letters[1:10] )
df3 <- df1
out <- smartbind( mylist <- list(df1,df2,df3))