No.22754 【R】do.call()関数を用いたリスト(複数のデータフレーム)のmerge  【明石】 2019/06/16(Sun) 09:50

青木先生 様;

お忙しいところを失礼いたします,明石と申します。
毎々,ご丁寧なご教示をいただき,誠にありがとうございます。
改めて,御礼を申し上げます。

青木先生にご教示いただきたいことが出てきました。
何卒どうぞよろしくお願いいたします。

--------------------------------------------------

リスト(複数のデータフレーム)のmergeを,forループで順次mergeするのではなく,
do.call()関数を用いて,もし書けるようならば,ご教示をお願いいたします。

do.call(rbind, list) にならい,
do.call(merge, list) のように,もし書けたとしたら,どのように書けるのか興味があります。
# tempフォルダ下にある,csvファイルのファイル名を取得

path <- setwd("C:/temp")
names <- list.files(path, pattern="csv")
nn <- length(names)

d <- list(nn)

loop <- 1: nn

for (i in loop) {
d[[i]] <- read.table(names[i], header=TRUE, sep=",", stringsAsFactors=F)
}

# リスト d に格納されている nn個のデータフレームは,いずれも同じ,mergeの属性 "支店名"をもっています。
# 要素の添字に沿って,完全外部結合を順次,繰り返したいと思います。

for (i in loop) {
if( i == 1) {
dat <- d[[1]]
} else {
dat <- merge(dat, d[[i]], by.x="支店名", by.y="支店名" , all.x = TRUE, all.y = TRUE ,no.dups = F)
}
}
もし,do.call(merge, d) のように書けるようならば,ご教示をいただきたいと思います。

お手数をおかけいたします。
何卒どうぞよろしくお願いいたします。

No.22756 Re: 【R】do.call()関数を用いたリスト(複数のデータフレーム)のmerge  【青木繁伸】 2019/06/16(Sun) 12:34

別に do.call でなくても,簡単に書きたいということなんでしょうか?

Reduce を使うのはいかが?
set.seed(11111)
d <- vector("list", 3)
d[[1]] <- data.frame(a=1:5, b=letters[1:5])
d[[2]] <- data.frame(a=c(1,3,5,6,8), c=LETTERS[1:5])
d[[3]] <- data.frame(a=c(2,4,5,7,9), d=rnorm(5))

merge2 <- function(x, y) merge(x, y, all.x = TRUE, all.y = TRUE, no.dups = FALSE)
Reduce(merge2, d)
一行で書くと
Reduce(function(x, y) merge(x, y, all.x = TRUE, all.y = TRUE, no.dups = FALSE), d)
なお,for を使う場合も,以下のようにすれば十分簡潔に書けるのでは?
x <- d[[1]] # 結果の初期化は,最初のデータフレームを代入
for (i in 2:length(d)) { # 2 番目以降のデータフレームをマージ
x <- merge(x, d[[i]], all.x = TRUE, all.y = TRUE, no.dups = FALSE)
}
x
どのように書いても,以下のような結果になると思いますが。
  a    b    c            d
1 1 a A NA
2 2 b <NA> 0.003630422
3 3 c B NA
4 4 d <NA> 0.798122717
5 5 e C 0.893397342
6 6 <NA> D NA
7 7 <NA> <NA> -1.195893897
8 8 <NA> E NA
9 9 <NA> <NA> -1.269878611

No.22757 Re: 【R】do.call()関数を用いたリスト(複数のデータフレーム)のmerge  【明石】 2019/06/16(Sun) 16:41

青木先生 様;

お忙しいところを失礼いたします,明石と申します。

先生がお書きになられたように,簡潔に書きたいというのが意図です。
そこで,do.call()関数に着目しました。

幾つかの方法をお示しくださいましたので,よく理解できました。
reduse()関数を初めて知りましたので,これを機会に勉強させていただきます。

今回も助けていただき,大変に助かりました。
誠にありがとうございました。

● 「統計学関連なんでもあり」の過去ログ--- 048 の目次へジャンプ
● 「統計学関連なんでもあり」の目次へジャンプ
● 直前のページへ戻る