dfの結合

Rでデータフレームを結合する場合,下方向にはrbind(row bind), 右方向にはcbind(column bind)の各関数を使うのが一般的だが,これらは結合対象の複数のデータフレームで列数/行数が揃っていないと使えない.

問題

きょう,あるデータを扱っていて,以下のようなケースに遭遇した(セルの中は架空).

df1 <- data.frame(a = 1:3, b = c("a", "b", "c"), e = c(1, 3, 5))
df2 <- data.frame(a = 7:9, b = c("t", "t", "t"), c = 4:6, d = c("q", "w", "e"), e = c(6, 6, 6))

表にすると以下のようになる.

##   a b e
## 1 1 a 1
## 2 2 b 3
## 3 3 c 5
##   a b c d e
## 1 7 t 4 q 6
## 2 8 t 5 w 6
## 3 9 t 6 e 6

つまりdf2にはdf1にはない二つの列(cとd)が入っているが,それ以外はdf1と同じ列名の列をもっている.

このような状況で,df2df1にはない列(cとd)を除去したうえでdf1df2を下方向に結合させる必要が生じた.

従来の解決方法

すぐに思いつくのは以下のようなスクリプトであろう.

df2a <- df2[ , c(-3, -4)]
rbind(df1, df2a)

#あるいは
df2a <- df2[ , c(1, 2, 5)]
rbind(df1, df2a)

#あるいは
df2a <- df2[ , c("a", "b", "e")]
rbind(df1, df2a)
##   a b e
## 1 1 a 1
## 2 2 b 3
## 3 3 c 5
## 4 7 t 6
## 5 8 t 6
## 6 9 t 6

1番目と2番目の例では列の番号を指定しており,3番目の例では直接列名を指定している.

しかし,分析が進むに従って変数(列)の出し入れが増えることが予想されるので,列の番号は変わる可能性があり,列番を指定するやり方はやりたくない.

とはいえ,ここでは結合するのは3列だが,実際には数十列あるので,いちいち結合する列名を書くのも面倒すぎる.

したがって,上の3例とは異なる方法が必要となる.おそらく,以下がいい方法だろう.

よいと思われるスクリプト

df2a <- c(which(names(df2) == "c"), which(names(df2) == "d"))
df2b <- df2[ , -df2a]
rbind(df1, df2b)
##   a b e
## 1 1 a 1
## 2 2 b 3
## 3 3 c 5
## 4 7 t 6
## 5 8 t 6
## 6 9 t 6

結合する列ではなく,結合しない列のリストdf2aをつくり,それをデータフレームdf2から引くことで結合されるべき列のデータフレームdf2bを得るやり方である.

いずれにせよ結合しない列の列名は書くことになるが,今回の場合,結合しない列のほうが少なかったので,結合する列名を全部書くよりは楽である.

さらに,列番は直接書きたくないので,which(names(df2) == "c")などとして,列名を使って列番を表す.これで,列の追加や削除で列番が変わっても大丈夫である.


結合する列が少なければ3例のようにオーソドックスにやればいいと思うが,今回のように,結合されるべき大半の列の中に結合されるべきでない列が割り込んでいるような場合は,上のやり方がよさそうだ.