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
この例のリストには3つの要素しかありません。ただし、任意の数の要素を処理できるソリューションを探しています。
Reduce
、1つのライナーソリューションを使用できます。
Reduce(merge,mylist)
names age score country
1 John 21 22 US
2 Sam 22 25 SA
素早く汚い例:
_merge(merge(df1, df2),df3)
_
[〜#〜] edit [〜#〜]-ここで非常によく似た質問: リスト内の複数のdata.framesを同時にマージ =
解決:
_merged.data.frame = Reduce(function(...) merge(..., all=F), my.list)
_
免責事項-私が@Charlesの回答から変更したのは、T
ではなくmerge(..., all=F)
を作成することだけでした-この方法で、目的の出力が得られます。
それを示すためだけに別の方法で行うことができます...
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))