cbindではNULLとデータフレームを結合できない
https://qiita.com/kattsu2003/items/7d0395d69fc7ca32556d
とあったが,そもそもそんなことはないし,もっとちゃんとした解決法があるよという話。
解決法
根本的には,「データフレームの結合は merge を使いましょう」ということ。
今回は,列方向の結合ということで,元記事は,「それぞれのデータフレームの行は同一サンプルのもの」ということが前提のようだ。
まあ,そいういうこともあるが,一般的には,それぞれのデータフレームの行は,同じ対象者についてのデータではないかもしれないし,幾つかの対象者のデータは欠損しているかもしれない。というのがよくある話。
そこで,最終的な解決法は「各データフレームに共通する何らかのキー(最もあり得るのは,データの個人番号など)を基準として結合する」ということではないか。
例として,以下のようなデータフレームを考えよう。それぞれのデータフレームは共通する項目 id を含む。それぞれのデータフレームにすべての id のデータが存在する訳ではない。
> df1= data.frame(id=c(1, 2, 3, 4), x=c(3, 2, 1, 3))
> df2 = data.frame(id=c(1, 2, 4, 5), y=c(1, 3, 2, 4))
> df3 = data.frame(id=c(2, 4, 5), z=c(1.3, 3.5, 1.5))
> df1
id x
1 1 3
2 2 2
3 3 1
4 4 3
> df2
id y
1 1 1
2 2 3
3 4 2
4 5 4
> df3
id z
1 2 1.3
2 4 3.5
3 5 1.5
3つのデータフレームは,共通する id という変数で「マージすべき」ものである。
マージする種(基)となるのは(何でもよいが)最初のデータフレームとしよう。これに,他のデータフレームを付加するわけだ。
> dfall = df1
マージされるデータフレームは,リストとして列挙しておく(ここ!だいじ。c() ではなく list()。実際,私も,最初ハマった😂)
> dfs = list(df2, df3)
実際の結合(マージ)は,以下のような for ループで行う。マージする種に他のデータフレームを順次マージしていくわけである。
> for (i in dfs){
+ dfall = merge(dfall, i, all=TRUE)
+ }
出来上がるデータフレームは以下のごとし。
それぞれのデータフレームに存在しない id の変数には NA が割り当てられている。
> dfall
id x y z
1 1 3 1 NA
2 2 2 3 1.3
3 3 1 NA NA
4 4 3 2 3.5
5 5 NA 4 1.5
merge のオプションは all=TRUE 以外もありうるだろう。
なぜこのような記事を書いたか
この qiita は開かれた掲示板(古!今はなんていうのかな)のはずなのに,記事に対してコメントしても,元記事投稿者がなんのコメントも返さないということがよくある(実によくある)。
なんでだろう。公衆の面前で恥をかかされたと憤っているのだろうか。
こちらとしては,少しでもいい情報(より正しい情報)を発信できるようにと思っているだけなんだけどなあ。