ggplot2で100%積み重ね棒グラフの真ん中に値を表示させたい

#はじめに
Rのggplot2で棒グラフを作成する際数字を入れたい場面があります。

<img width="766" alt="スクリーンショット 2019-05-28 9.48.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282698/dce54e8f-f0f6-963c-0dde-5b849721252c.png">


やり方をいつも忘れてしまうので、いつもkaztanさんの記事やR Graphics Cookbook, 2nd editionを参考にさせて頂いています。ただこの方法は`position = "stack"`の積み上げ棒グラフで、縦軸はカウントデータになっています。

`position = "fill"`の100%積み上げ棒グラフでも数値を真ん中に配置する方法を調べようとしたのですが、google検索の上位表示に出てきませんでした。

今回は備忘録のために自分が行った方法を紹介します。

#ライブラリの読み込み

```R
#tidyverseパッケージを使ったことがなければインストールします
if(!require(tidyverse)) install.packages("tidyverse", repos = "http://cran.us.r-project.org")

#既にtidyverseパッケージをインストールしている方はライブラリで読み込みます
library(tidyverse)
```

今回はggplot2を使うためにtidyverseパッケージを使います。

#データの作成

```R
#データ作成
set.seed(2019)
sex <- sample(c("male", "female"), size = 200, replace = TRUE)
category <- sample(c("A","B","C","D"), size = 200, prob = c(0.2, 0.3, 0.4, 0.1), replace = TRUE)
dat <- data.frame(sex, category)
rm(sex, category)
summary(dat)
```
```R
#結果
     sex      category
 female: 91   A:33    
 male  :109   B:63    
              C:90    
              D:14  
```

```R
#積み上げ棒グラフ(position = "fill")
dat %>% 
  group_by(sex, category) %>% 
  summarize(count = n()) %>% 
  arrange(sex, desc(category)) %>% 
  mutate(label_y = (cumsum(count) - 0.5 * count) / sum(count)) %>%
  ggplot2::ggplot(aes(x = sex))+
  geom_bar(aes(y = count, fill = category), stat = "identity", position = "fill")+
  geom_text(aes(label = count, y = label_y))+
  scale_y_continuous(labels = scales::percent)
```
<img width="559" alt="スクリーンショット 2019-05-28 8.25.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282698/2ec11336-84e4-ad98-b8da-c10f27ddbb61.png">

`group_by`→`summarize`関数で集計した後グラフを作成しています。
棒グラフを作るのは`geom_bar`、数値は`geom_text`を用いています。

##ポイント1
`geom_bar`関数で作る棒グラフはカテゴリーの順番毎に上から並びます。
cumsum関数で累積和を求めるのですが、そのまま行うと累積和の順番が逆になります。
そのため`arrange(sex, desc(category))`で逆順にしています。

```R
#arrangeを使わなかった場合
dat %>% 
  group_by(sex, category) %>% 
  summarize(count = n()) %>% 
  mutate(label_y = (cumsum(count) - 0.5 * count) / sum(count)) 
>
  sex    category count label_y
  <fct>  <fct>    <int>   <dbl>
1 female A           16  0.0879
2 female B           31  0.346 
3 female C           36  0.714 
4 female D            8  0.956 
5 male   A           17  0.0780
6 male   B           32  0.303 
7 male   C           54  0.697 
8 male   D            6  0.972 
```
```R
#arrangeを使った場合
dat %>% 
  group_by(sex, category) %>% 
  summarize(count = n()) %>% 
  arrange(sex, desc(category)) %>% 
  mutate(label_y = (cumsum(count) - 0.5 * count) / sum(count)) 
>
  sex    category count label_y
  <fct>  <fct>    <int>   <dbl>
1 female D            8  0.0440
2 female C           36  0.286 
3 female B           31  0.654 
4 female A           16  0.912 
5 male   D            6  0.0275
6 male   C           54  0.303 
7 male   B           32  0.697 
8 male   A           17  0.922 
```

##ポイント2
通常の積み上げ棒グラフであれば`mutate(label_y = cumsum(count) - 0.5 * count)`で高さを求めます。

100%積み上げ棒グラフの場合は、上で求めた値を`sum(count)`で割ることで割合になります。

#まとめ

色々書いたのですが、結果通常の積み上げ棒グラフで行う方法に対し`sum()`で割ればよいという話でした。

#参考

[ggplot2で積み重ね棒グラフに値を表示させたい](https://qiita.com/kazutan/items/f26db670412906f00e4c)

[R Graphics Cookbook, 2nd edition](https://r-graphics.org/chapter-bar-graph)