備忘ログ

チラシの裏的備忘録&メモ

Rのggplot2でデータにない値を凡例に反映させるメモ

Rの{ggplot2}でグラフを書くときに色分けしたりすると使われている値をみて凡例をいい塩梅に調整してくれるので大体の場合はそのままでありがたい。

が、たまに使ったデータ上は値がないが、凡例上は値を入れたいということがある。例えば、{dabasets}パッケージのmtcarscylは気筒数でこのこのデータセット上は4気筒、6気筒、8気筒しかないが、5気筒や7気筒の車もあるだろうし、そいういうのを凡例に反映させたいなと思ったときなど。

このデータの場合はデータセット上存在しないのでそんなに必要性が感じられないが、さらに5気筒や7気筒の車の燃費データみたいなのを集めた時に一定の要素でフィルタリングしたグラフを作った時に特定の気筒数のデータが消えてグラフ化したものを並べて表示するのではなく別スライドに表示する時に凡例を揃えたいという欲求に駆られる。

のでそういうのを解決する方法をメモしておく。ベスプラかわからないし、ちょっと値の数が多くなると大変なのでもっと良い方法があるかもしれない。楽な方法を知りたい。

まずは、mtcarsデータの横軸に燃費(mpg)、縦軸に排気量(disp)でプロットし、気筒数(cyl)で色分けする。

library(ggplot2)

ggplot(mtcars) +
  geom_point(aes(x = mpg, y = disp, color = cyl))

f:id:indenkun:20210921102350p:plain

このままだとcylが連続する数字のように扱わえれ色がグラデーションになっててしまうが今回の気筒数は4.5気筒みないな値は基本的に存在し得ないので、因子型化して個別の値だよ明示しておく(別に文字列型でもよいが)。ついでに4~8のレベルを与えて、今回のデータには5気筒や7気筒はないけどそういう値もあり得る的なのを明示しておく。

mutate()使いたいので{dplyr}使う。

library(dplyr)
## 
##  次のパッケージを付け加えます: 'dplyr'

##  以下のオブジェクトは 'package:stats' からマスクされています: 
## 
##      filter, lag

##  以下のオブジェクトは 'package:base' からマスクされています: 
## 
##      intersect, setdiff, setequal, union
mtcars %>% 
  mutate(cyl = factor(cyl, levels = 4:8)) %>% 
  ggplot() +
  geom_point(aes(x = mpg, y = disp, color = cyl))

f:id:indenkun:20210921102409p:plain

ぞれぞれの気筒数で色が別れて見やすいが、因子型で5気筒や7気筒の存在を匂わせても凡例には反映されない。

反映させたかったらscale_color_manual()で明示的に値と色を指定してやるとできる(重ねていうがこれがべスプラかどうかわからない)。

mtcars %>% 
  mutate(cyl = factor(cyl, levels = 4:8)) %>% 
  ggplot() +
  geom_point(aes(x = mpg, y = disp, color = cyl)) +
  scale_color_manual(values = c("4" = "2", "5" = "3", "6" = "4", "7" = "5", "8" = "6"))

f:id:indenkun:20210921102428p:plain

scale_color_manual()values引数で値とその値の指定したい色を選んでやると強制的に色が割り当てられて凡例に反映される。指定したい色は色名を直接指定しても良いし、色に拘りがないし(色のセンスもないので)今回は2番("2")に振られている色を4の値に割り振るというふうにしている(ちなみに1番で振られる色は黒になるので今回は2番から割り振っている)。

こうすると次のグラフで5気筒とかのデータが入ったグラフを出しても凡例が同じになって統一感があって色味も合わせやすいので嬉しいかもしれない。

ただし、この方法法はない値も強制的に割り振りができるので注意が必要だし、入力するものが多くて面倒くさいはある。

mtcars %>% 
  mutate(cyl = factor(cyl, levels = 4:8)) %>% 
  ggplot() +
  geom_point(aes(x = mpg, y = disp, color = cyl)) +
  scale_color_manual(values = c("3" = "1","4" = "2", "5" = "3", "6" = "4", "7" = "5", "8" = "6"))

f:id:indenkun:20210921102443p:plain

こんな風に因子型のレベルでは4~8なのに、凡例は3~8みたいなのも作れる。