ggplot2でヒストグラムを描くときに外枠だけに線を引きたい
タイトルの通り、「ggplot2でヒストグラムを描くときに外枠だけ線を引きたい」という質問を受けました。図にすると以下のような状況です。
枠線を付けたいときにパッと思いつくのは、引数colour
を指定することですが、そうすると下図・右のようになってしまいます。
library(ggplot2) bw <- diff(range(faithful$waiting))/20 # 左図 ------------------------------------------------- ggplot(data = faithful, mapping = aes(x = waiting)) + geom_histogram(binwidth = bw, fill = "skyblue") + labs(title = "通常のヒストグラム") # 右図 ------------------------------------------------- ggplot(data = faithful, mapping = aes(x = waiting)) + geom_histogram(binwidth = bw, fill = "skyblue", colour = "darkblue") + labs(title = "全ての棒に枠線を付けたヒストグラム")
で、どうやるんだろうと調べてみました。安直に「ggplot2 histogram only outline」というググり方をしましたが、幸いにもすぐにヒットしました。ggplot2の調べ物は英語でググるのが吉です。
参考:can I draw a histogram that has an outline around the entire shape, but not the individual bars?
ヒストグラムを描くときに、Y軸にマッピングする変数を省略するのではなく、mapping = aes(y = ..density..)
としてkernel density estimateをマッピングすることを明示したうえで、geom_step()
を用いてヒストグラムの輪郭だけを描くんですね。
あとはヒストグラムのレイヤを重ねてやれば、見た目上は外枠だけに線が描かれたように見えるはずです。
ただし注意が必要なのは、ヒストグラムはY軸が度数(count)である点です。そこで以下のページを参考に、ひと工夫します。ポイントは、geom_step(mapping = eval(bquote(aes(y=..count..)))
というところです。
参考:データのhistogramと確率密度関数を同時に描きたい
勝った、第3部完!
dens <- density(faithful$waiting) bw <- diff(range(faithful$waiting))/20 ggplot(data = faithful, mapping = aes(x = waiting)) + geom_histogram(binwidth = bw, fill = "skyblue") + geom_step(mapping = eval(bquote(aes(y=..count..))), stat = "bin", binwidth = bw, colour = "darkblue") + xlim(range(dens$x))
ずれとるやんけ!
考えてみたらそりゃそうで、geom_step()
が描く線の始点は、各階級幅の中央になるので、階級幅の半分だけずれることになります。仕方がないので、引数position
をいじって、X軸のずれを補正します。
dens <- density(faithful$waiting) bw <- diff(range(faithful$waiting))/20 ggplot(data = faithful, mapping = aes(x = waiting)) + geom_histogram(binwidth = bw, fill = "skyblue") + geom_step(mapping = eval(bquote(aes(y=..count..))), stat = "bin", binwidth = bw, position = position_nudge(x = -bw/2), #←階級幅の半分だけ左にずらしている colour = "darkblue") + xlim(range(dens$x))
完成。
ただWarning messages出てるんですよね...。うーん、もうちょっと改善の余地がありそうです。もしもっと適切な方法があれば教えていただけたら嬉しいです。
Warning messages: 1: Removed 2 rows containing missing values (geom_bar). 2: Removed 1 rows containing missing values (geom_path).
追記:
atusyさん(@Atushi776)から、「stat_bin()
を使うとよい & 引数pad = TRUE
を書くとよい」とご提案いただきました。ありがとうございます! 確かにこちらのほうがシンプルで良いですね。そしてWarning messagesも出ない!
bw <- diff(range(faithful$waiting))/20 ggplot(data = faithful, mapping = aes(x = waiting)) + geom_histogram(binwidth = bw, fill = "skyblue") + stat_bin(binwidth = bw, colour = "darkblue", geom = "step", position = position_nudge(x = -bw / 2), pad = TRUE)
Enjoy !