1. ホーム
  2. r

[解決済み】リスト内の複数のdata.frameを同時にマージする方法

2022-03-28 15:53:27

質問

多くのdata.frameのリストがあり、それをマージしたいのですが、どうすればよいですか?問題は、それぞれの data.frame が行と列の数で異なっていることですが、それらはすべてキーとなる変数 ( "var1""var2" を以下のコードで説明します)。もしdata.frameのカラムが同じであれば、私は単に rbind に対して、plyrの rbind.fill が、今回のデータではそうなっていない。

なぜなら merge コマンドは2つのdata.frameにしか使えないので、インターネットにアイデアを求めました。これは こちら これは、当時私が持っていたR 2.7.2で完璧に機能しました。

merge.rec <- function(.list, ...){
    if(length(.list)==1) return(.list[[1]])
    Recall(c(list(merge(.list[[1]], .list[[2]], ...)), .list[-(1:2)]), ...)
}

そして、このような関数を呼び出すのです。

df <- merge.rec(my.list, by.x = c("var1", "var2"), 
                by.y = c("var1", "var2"), all = T, suffixes=c("", ""))

しかし、2.11や2.12を含む2.7.2以降のRのバージョンでは、このコードは以下のエラーで失敗します。

Error in match.names(clabs, names(xi)) : 
  names do not match previous names

(ちなみに、このエラーについて他の文献を見ると 他の場所 を解決できないままです)。

これを解決する方法はあるのでしょうか?

どのように解決するのですか?

もう一つの質問は、具体的に Rでdplyrを使用して複数の左結合を実行する方法 . この質問は、この質問と重複しているとマークされていたので、以下の3つのサンプルデータフレームを使って、ここで回答します。

x <- data.frame(i = c("a","b","c"), j = 1:3, stringsAsFactors=FALSE)
y <- data.frame(i = c("b","c","d"), k = 4:6, stringsAsFactors=FALSE)
z <- data.frame(i = c("c","d","a"), l = 7:9, stringsAsFactors=FALSE)

2018年6月更新 : マージを実行する3つの異なる方法を表すために、答えを3つのセクションに分けました。おそらく purrr を使用している場合は ティディバース パッケージを使用します。以下、比較のために、同じサンプルデータセットを使った基本的なRバージョンをご覧ください。


1) で結合する reduce から purrr パッケージを使用します。

purrr パッケージは reduce 関数は、簡潔な構文を持っています。

library(tidyverse)
list(x, y, z) %>% reduce(left_join, by = "i")
#  A tibble: 3 x 4
#  i       j     k     l
#  <chr> <int> <int> <int>
# 1 a      1    NA     9
# 2 b      2     4    NA
# 3 c      3     5     7

また、他の結合を行うこともできます。 full_join または inner_join :

list(x, y, z) %>% reduce(full_join, by = "i")
# A tibble: 4 x 4
# i       j     k     l
# <chr> <int> <int> <int>
# 1 a     1     NA     9
# 2 b     2     4      NA
# 3 c     3     5      7
# 4 d     NA    6      8

list(x, y, z) %>% reduce(inner_join, by = "i")
# A tibble: 1 x 4
# i       j     k     l
# <chr> <int> <int> <int>
# 1 c     3     5     7


2) dplyr::left_join() ベースR付き Reduce() :

list(x,y,z) %>%
    Reduce(function(dtf1,dtf2) left_join(dtf1,dtf2,by="i"), .)

#   i j  k  l
# 1 a 1 NA  9
# 2 b 2  4 NA
# 3 c 3  5  7


3)ベースR merge() ベースRで Reduce() :

また、比較のために、Charlesの回答に基づいて左結合のベースRバージョンを以下に示します。

 Reduce(function(dtf1, dtf2) merge(dtf1, dtf2, by = "i", all.x = TRUE),
        list(x,y,z))
#   i j  k  l
# 1 a 1 NA  9
# 2 b 2  4 NA
# 3 c 3  5  7