dplyr と tidyr でクロス集計表をつくる group_by() & tally() 編
ゴールデンウィークはRと格闘してました。前回と今回はその記録です。
前回とはちょっと違った方法で、クロス集計表を作ってみます。結果は同じです。今回は group_by() を使って列をグループ化する、という作業が1つ増えています。検索すると、今回の方法が主流のようです。前回はこちら↓
■必要なパッケージ
dplyr
tidyr
■使う関数
group_by
tally
spread
■扱うデータ
haisya01.txt(前回と同じデータです)
まずデータの確認と編集用データの作成から。来院動機っていうのは、治療のために歯医者さんに行ったのか、それとも定期検診なのか、別の理由なのかを示しています。
> df <- haisya01.txt
> head(df)
user_id 性別 年齢 来院動機 費用負担 来院経路
1 1 男性 48 治療 保険 ホームページ
2 2 男性 55 治療 保険 ホームページ
3 3 男性 55 治療 保険 友達・知人紹介
4 4 男性 57 治療 保険 その他
5 5 男性 47 治療 自費 その他
6 6 女性 27 治療 保険 その他
クロス集計したいのは性別と来院動機です。性別ごとに来院動機の数を知りたいと思うので、集計します。下ごしらえとして、性別と来院動機をグループ化します。それを df2 に入れて確認。
> df2 <- group_by(df, 性別, 来院動機)
> df2
Source: local data frame [500 x 6]
Groups: 性別, 来院動機
user_id 性別 年齢 来院動機 費用負担 来院経路
1 1 男性 48 治療 保険 ホームページ
2 2 男性 55 治療 保険 ホームページ
3 3 男性 55 治療 保険 友達・知人紹介
4 4 男性 57 治療 保険 その他
5 5 男性 47 治療 自費 その他
6 6 女性 27 治療 保険 その他
7 7 女性 33 治療 保険 家族紹介
8 8 男性 50 検診 保険 その他
9 9 男性 44 治療 保険 家族紹介
10 10 女性 43 検診 保険 建物・看板を見て
.. ... .. .. ... ... ...
「Groups: 性別, 来院動機」という表示が出てきました。どうやらうまくいったようです。では、集計。集計するときに使うのは、tally() という関数です。count() とは違って「tally(データ名)」でいいです。
> df3 <- tally(df2)
> df3
Source: local data frame [6 x 3]
Groups: 性別
性別 来院動機 n
1 女性 その他 9
2 女性 検診 131
3 女性 治療 152
4 男性 その他 8
5 男性 検診 77
6 男性 治療 123
前回の count(df2, 性別, 来院動機) と同じ結果が出てきました。あとは spread() を使って来院動機ごとに n の数値を並び替えて、df4 に入れます。
> df4 <- spread(df3, 来院動機, n)
> df4
Source: local data frame [2 x 4]
性別 その他 検診 治療
1 女性 9 131 152
2 男性 8 77 123
むむ、やっぱり昇順に並んでいる。前回は select() で日本語の引数を使ったのだダメだったのかもしれない。禁断の添字を使ってみます。1列目、4列目、3列目、2列目の順で並び替えて、df5 に格納。
> df5 <- df4[, c(1,4,3,2)]
> df5
Source: local data frame [2 x 4]
性別 治療 検診 その他
1 女性 152 131 9
2 男性 123 77 8
無事、文字化けせずにすみました。添字を使ってしまったのはちょっと悔しいです。Rのせいかな? Rstudio なのかな? select() のせいかな? まあいいや。クリティカルではないし。
以上、tally() を使ったクロス集計表の作り方でした。んー、自分的には count() が好きかも。グループ化も勝手にやってくれますし。