ggplot2 で facet ごとのヒストグラムに平均値の線を引きたい。
例えば次のような感じ。
Rコミュニティの Slack である r-wakalang で聞いたところ、即回答がもらえただけでなく、いろいろなやり方を教わったのでメモしておく。 みなさんありがとう。
基本作図
まずはデータを準備する。 ここでは有名な iris データから数値カラム x と facet を作るためのカテゴリカル変数 group を持つデータフレームを作成する。
data(iris) # iris データの読み込み(通常は必要ない) library(dplyr) # データの作成 data <- iris %>% select(x = Sepal.Length, group = Species) # データ内容の確認 head(data)
x group 1 5.1 setosa 2 4.9 setosa 3 4.7 setosa 4 4.6 setosa 5 5.0 setosa 6 5.4 setosa
このデータに対して、グループごとにヒストグラムを作成する。
library(ggplot2) ggplot(data, aes(x)) + geom_histogram() + facet_wrap(~group, ncol=1)
この3つのヒストグラムに対して、それぞれのグループの平均値を表す垂直線を追加したいというのが今回の目的。
facet ごとの集計値の扱い
ggplot2 で facet ごとに集計値を扱う場合は、別データとして集計済みのデータを用意する。
例えば今回は平均値の垂直線を引きたいので、次のように平均値を計算したデータフレームを用意する。
data_summary <- data %>% group_by(group) %>% summarise(mean_x = mean(x)) data_summary
group mean_x 1 setosa 5.01 2 versicolor 5.94 3 virginica 6.59
この集計データを用いて平均値をグラフに書き込むことができる(ura_hoxom さん)。
ggplot(data, aes(x)) + geom_histogram() + facet_wrap(~group, ncol=1) + geom_vline(data = data_summary, aes(xintercept = mean_x), color = "red")
目的は達成された。
他の方法
他の方法も教えてもらった。 ggplot2 では集計データを用意しなくても、集計用の関数を渡すと自動的にデータ集計してくれるらしい。
例えば、次のようにグループごとに平均値を集計する関数を用意する。
mean_by_group = function(d) { d %>% group_by(group) %>% summarize(mean_x = mean(x)) }
集計済みデータの代わりに、これを ggplot2 に渡すことができる(heavywatal さん)。
ggplot(data, aes(x)) + geom_histogram() + facet_wrap(~group, ncol=1) + geom_vline(data = mean_by_group, aes(xintercept = mean_x), color = "red")
また、集計する関数については次のように簡潔に作成できる(yutannihilation さん)*1。
mean_by_group = . %>% group_by(group) %>% summarize(mean_x = mean(x))
まとめ
というわけで、みなさんいろいろ教えてくださってありがとうございました。
R-wakalang への参加の仕方については次の資料を参考にしてください。
- qiita.com
- Rおじさんの異常な即回答または私は如何にして心配するのを止めてr-wakalangで回答するようになったか / how-i-learned-to-stop-worrying-and-answer - Speaker Deck
Enjoy!
*1:これは magrittr の機能らしい。https://github.com/tidyverse/magrittr#building-unary-functions 参照。