クロス集計〜公式:dplyr + tidyr = (xtabs|(f)table)
特にやりたくはないんだけど、クロス集計をしなければならない状況がある。そんなときExcelを使ってもいいんだろうけど、レポーティングまで含めてRでやってしまいたい、あると思います。そんな時どうするかって話。
Rには既に
- xtabs関数
- (f)table関数
というクロス集計してくれる関数があるんだけど、こいつらの使い方覚えるのめんどくさい(毎度ググってる)し、特に他のデータハンドリング系関数との相性もよくはないので、全てdplyr&tidyrパッケージで済ませたい。
なので、以下、xtabs&table関数の結果と同じになるように、dplyr&tidyrで書いてみる。
使用するパッケージ
当然、dplyr&tidyrは使う。
library(dplyr) library(tidyr)
dplyr, tidyrの使い方については
- plyr: データ分割-関数適用-再結合を効率的に - Heavy Watal
- tidyr: シンプルなデータ変形ツール - Heavy Watal
- R dplyr, tidyr でのグルーピング/集約/変換処理まとめ - StatsFragments
がよくまとまっていて、大変ありがたい。
使用するデータ
なんかよくわからんけどxtabsの例に載ってたデータを使ってみることした。適当なデータフレームですね。
> df <- as.data.frame(UCBAdmissions) > head(df) Admit Gender Dept Freq 1 Admitted Male A 512 2 Rejected Male A 313 3 Admitted Female A 89 4 Rejected Female A 19 5 Admitted Male B 353 6 Rejected Male B 207
公式1:xtabs(~X+Y) = group_by(X, Y) %>% tally %>% spread(X, n)
クロス集計において、その”キーの組み合わせ数”をカウントするコードは以下。
> df %>% + xtabs(~Gender+Admit, .) Admit Gender Admitted Rejected Male 6 6 Female 6 6 > > df %>% + group_by(Gender, Admit) %>% + tally %>% + spread(Admit, n) Source: local data frame [2 x 3] Gender Admitted Rejected 1 Male 6 6 2 Female 6 6
公式2: xtabs(Z~X+Y) = group_by(X, Y) %>% summarize(n=sum(Z)) %>% spread(X, n)
クロス集計において、”各キーの○○要素の合算値”を計算するコードは以下。
> df %>% + xtabs(Freq~Gender+Admit, .) Admit Gender Admitted Rejected Male 1198 1493 Female 557 1278 > > df %>% + group_by(Gender, Admit) %>% + summarize(n=sum(Freq)) %>% + spread(Admit, n) Source: local data frame [2 x 3] Gender Admitted Rejected 1 Male 1198 1493 2 Female 557 1278
公式3: table(X, Y)= group_by(X, Y) %>% tally %>% spread(Y, n)
マニュアルにあるtable関数の例に合わせて、ここでは、別なデータに対して実行。出力結果がちょいと違うけど、まぁいいか&NAはあとで0埋めしよう。
> b <- factor(rep(LETTERS[1:3], 10)) > d <- factor(rep(LETTERS[1:3], 10), levels=LETTERS[1:5]) > b [1] A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C Levels: A B C > d [1] A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C Levels: A B C D E > table(b, d) d b A B C D E A 10 0 0 0 0 B 0 10 0 0 0 C 0 0 10 0 0 > df <- data.frame(b, d) > df %>% + group_by(b, d) %>% + tally %>% + spread(b, n) Source: local data frame [3 x 4] d A B C 1 A 10 NA NA 2 B NA 10 NA 3 C NA NA 10
結論
総じてdplyr&tidyrの方がタイプ数が多くなるけど、余計なクラス構造&返り値を覚えなくていいので、私はdplyr&tidyrでいきたい。