R言語:複数カテゴリboxplot+jitterplot問題

前回の続き。
嵌ったのは個々から。

## 起こったこと

boxplot+jitterplotで示せばt検定しろとか言われないと理解したワイ。
片っ端からbox jitterしていたのだ。
問題は欠損カテゴリが出現したときに起こった。


```
ggsave2 <- function(plot, wid=9, hei=9){
  plot_name <- deparse(substitute(plot))
  file_name <- paste(plot_name, ".png", sep = "",collapse = "")
  ggsave(filename = file_name,plot = plot,device = "png",width = wid, height = hei,dpi = 300,units = "cm")
}

dmd <- diamonds %>%
  dplyr::filter(!as.character(cut) %in% c("Fair", "Good")) %>%
  dplyr::filter(as.character(color) %in% c("G", "H", "I")) %>%
  .[sample(x = 1:nrow(.), size = 500, replace = F),]
```
ってしておく。
ggsave2は、そのまま保存するようの関数だ。


```
dmd %>%
  head()
```
># A tibble: 6 x 10
>  carat cut       color clarity depth table price     x     y     z
>  <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
>1  0.52 Ideal     H     VS1      61      56  1699  5.15  5.23  3.17
>2  0.61 Ideal     I     SI2      61.1    57  1401  5.46  5.49  3.34
>3  0.31 Premium   H     VVS2     62.6    60   625  4.29  4.33  2.7 
>4  0.54 Very Good G     SI1      63.8    57  1392  5.16  5.19  3.3 
>5  0.33 Ideal     G     IF       61      57   925  4.45  4.48  2.72
>6  1.1  Ideal     G     SI1      62.3    56  5226  6.64  6.58  4.12

かんたんにはdiamondsのカテゴリ変数cutとcolorを少し絞った。
イメージとしてはカテゴリ変数の組み合わせとして10通り以下ぐらいがある状態を考えてほしい。

前回のbox+jitterするとこうだ。

```
p_boxjit <- ggplot()+theme_light()+
  geom_boxplot(data = dmd,
               aes(x=cut, y=carat), outlier.shape = NA)+
  geom_jitter(data = dmd,
               aes(x=cut, y=carat),
              color="red", size=0.7)
ggsave2(p_boxjit)
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676634/f6842bab-74c6-4ebb-9dd0-3594a4e3a6b0.png)

さて、2つのカテゴリ変数の組み合わせの数がそれほど多くないなら、一つのbox jitterで見てみたいと思うよね。
一応こうすればできる。

```
pallet_ad_man <- c("#e41a1c",
                   "#377eb8",
                   "#4daf4a")
pallet_ad_white <- c("#ffffff",
                     "#ffffff",
                     "#ffffff")

p_bj2 <-  ggplot()+theme_light()+
  geom_boxplot(data = dmd,
               aes(x=cut, y= carat, fill=color),
               outlier.colour = NA)+
  scale_fill_manual(values = pallet_ad_white)+
  geom_point(data = dmd,
             aes(x=cut, y=carat, color=color),
             position = position_jitterdodge(jitter.width = 0.7), size=0.6)+
  scale_color_manual(values = pallet_ad_man)

ggsave2(p_bj2, wid = 15)
```
結果はこうだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676634/40c1e59d-99f1-8a02-c6e7-5caa470087a7.png)

一応解説をすると、
boxplotの色はpallete_ad_whiteで全部白色に指定して、
jitter plotはgeom_pointで表現している。
でカテゴリ変数による横配置はpositon_jitterdodgeで実現する。

pallet_ad_manはpointでの色合いをしてしている。
これは完全に好み。
ただ、白色バックに黄色の点とか見にくいので適当に調整した。


ここまではいいだろう。
問題はここからだ。

特定の組み合わせに欠損があるとどうなるか。。。

```
dmd_lack <- dmd %>%
  dplyr::filter(!(cut == "Ideal" & (color %in% c("G", "I")))) 

p_bj3 <-  ggplot()+theme_light()+
  geom_boxplot(data = dmd_lack,
               aes(x=cut, y= carat, fill=color),
               outlier.colour = NA)+
  scale_fill_manual(values = pallet_ad_white)+
  geom_point(data = dmd_lack,
             aes(x=cut, y=carat, color=color),
             position = position_jitterdodge(jitter.width = 0.7), size=0.6)+
  scale_color_manual(values = pallet_ad_man)

ggsave2(p_bj3, wid = 15)

```
Ideal群でG, Iとなるrowが存在しない。そうすると結果としては以下だ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676634/3a570e3c-1375-b324-e12c-a1ddbbdb7471.png)

うーん美しくない。
Idealだけ無駄に横長になってしまって、全く嬉しくない。

boxplotだけなら、下のようにできる。

```
p_b3 <- ggplot()+theme_light()+
  geom_boxplot(data = dmd_lack,
               aes(x=cut, y= carat, fill=color),
               position = position_dodge2(preserve = "single",
                                          width = 0.5),
               outlier.colour = NA)
ggsave2(p_b3, wid =12)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676634/32c7d7df-6b25-3366-f7f6-aca0178ae34e.png)


だがboxplotじゃあ足りないんだ。

```
p_bj4 <-  ggplot()+theme_light()+
  geom_boxplot(data = dmd_lack,
               aes(x=cut, y= carat, fill=color),
               position = position_dodge2(preserve = "single",
                                          width = 0.5),
               outlier.colour = NA)+
  scale_fill_manual(values = pallet_ad_white)+
  geom_point(data = dmd_lack,
             aes(x=cut, y=carat, color=color),
             position = position_jitterdodge(jitter.width = 0.7), size=0.6)+
  scale_color_manual(values = pallet_ad_man)
ggsave2(p_bj4, wid = 15)

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676634/c4fd4644-1154-2b05-5259-50f9a37894a0.png)

これが欲しかった図である。
ggplot2のバージョン等ではうまくイカないことがあるようだ。

もう一つのやり方は、欠損カテゴリを、プロットするべき範囲外の値で充填してしまう方法である。

```
dmd_lack_fix <- dmd_lack %>%
  mutate(cut = factor(as.character(cut),
                      levels = c("Very Good", "Premium", "Ideal")),
         color = factor(as.character(color), 
                        levels = c("G", "H", "I"))) %>%
  tidyr::complete(cut, color, fill = list(carat = -100))
```
何をしているかというと、
tidyr::completeで欠損カテゴリを充填するんだけど、
個々での欠損カテゴリは、cutがFairとか、colorがA，みたいなのも充填されてしまうので、
コード中のカテゴリのみだよってファクターの振り直しをしている。
それからコンプリートだね。

この辺すごく抽象度が低くて嫌になるけど、ここでは許してほしい。

```
p_bj5 <-  ggplot()+theme_light()+
  geom_boxplot(data = dmd_lack_fix,
               aes(x=cut, y= carat, fill=color),
               outlier.colour = NA) +
  scale_fill_manual(values = pallet_ad_white)+
  geom_point(data = dmd_lack_fix,
             aes(x=cut, y=carat, color=color),
             position = position_jitterdodge(jitter.width = 0.7), size=0.6)+
  scale_color_manual(values = pallet_ad_man)+
  coord_cartesian(ylim = c(0.2, 2.7))
ggsave2(p_bj5, wid=15)

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676634/dced54cc-3935-1ccf-219c-8e6aa2d583d5.png)



やったぜ。