11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

R言語Advent Calendar 2024

Day 14

ggplotで色に色々悩んだ

Posted at

さいしょに

この記事はR言語 Advent Calendar 2024年の14日目の記事です。Advent Calendar に参加するのは2回目です。

モチベーション

ggplotのカラーパレット何が良いかな、と悩んでいました。というのも、ggplotのデフォルトのカラーパレットで2要素に色分けすると、ピンクと緑であまり良くないとされている組み合わせなのかな、と思ったからです。

それで色々調べたりしたのですが、結局結論まではたどり着いていません。ですが、とりあえず「こうやっておくのがベターかな」とはなったので、それをまとめます。

色覚異常について

以下のサイトによると、赤と緑の見分けがつきにくい人が男性で5%, 女性で0.2%いるとのことです。男性のうち5%というのは無視できない割合ですので、考慮した作図が求められます。

先天赤緑色覚異常の発生頻度は、日本人では男性の5%、女性の0.2%です。つまり、男性では20人に1人、女性では500人に1人の割合です。

色覚異常の方からの見え方について

下のサイトを主に参考にしています。程度問題の面もあるので、必ずこう見えるという訳ではないとのことですが、dichromatを使って色覚異常の影響を近似することが出来ます。試しにggplotのデフォルトであるhue_pal()で2要素の見え方をテストすると、色合いのイメージは変わりますが、まあ区別出来てるから大丈夫かあ、となります。もともと自分は赤と緑と思っていましたが、デフォルトでもちゃんと配慮されており、特に気を揉む必要はなかったと言えます。

ちなみに、Protanopiaは赤が見えにくいタイプ、Deutanopiaは緑が見えにくいタイプ、Trichromacyは3色見えるタイプ(一般的なタイプ)、Tritanopiaは青と黄色を区別しにくいタイプとのことです。

Rplot04.png

library(dichromat)
library(scales)
hue_colors <- hue_pal()(2)

# convert to the three dichromacy approximations
protan <- dichromat(hue_colors, type = "protan")
deutan <- dichromat(hue_colors, type = "deutan")
tritan <- dichromat(hue_colors, type = "tritan")

# plot for comparison
layout(matrix(1:4, nrow = 4)); par(mar = rep(1, 4))
recolorize::plotColorPalette(hue_colors, main = "Trichromacy")
recolorize::plotColorPalette(protan, main = "Protanopia")
recolorize::plotColorPalette(deutan, main = "Deutanopia")
recolorize::plotColorPalette(tritan, main = "Tritanopia")

複数の要素の場合

しかし、複数の要素に分けた場合、考慮が必要かなと思いました。宗さんと矢内さんのページによると、hue_pal()は循環する仕組みとなっているためか、Tritanopiaの方から見たら対称性のある似た色合いになってしまいます。

Rplot05.png

hue_colors <- hue_pal()(7)

# convert to the three dichromacy approximations
protan <- dichromat(hue_colors, type = "protan")
deutan <- dichromat(hue_colors, type = "deutan")
tritan <- dichromat(hue_colors, type = "tritan")

# plot for comparison
layout(matrix(1:4, nrow = 4)); par(mar = rep(1, 4))
recolorize::plotColorPalette(hue_colors, main = "Trichromacy")
recolorize::plotColorPalette(protan, main = "Protanopia")
recolorize::plotColorPalette(deutan, main = "Deutanopia")
recolorize::plotColorPalette(tritan, main = "Tritanopia")

また、Hannah Wellerさんのサイトではviridisが推奨されています。確かに、ここでシミュレーションした全てのタイプに対し、区別出来ているように見えます。

ただ個人的には、色合いが順番に変わっていくので、連続的な印象を与えかねないかな、とも思いました。まあ3つくらいであれば全然問題無いと思いますが、下のような7要素だと、1から7に徐々に変化していくもの、と見られなくもないからです。

viridis.png

viridis_pal <- scale_color_viridis_d()
viridis_color <- viridis_pal$palette(7)
  
# convert to the three dichromacy approximations
protan <- dichromat(viridis_color, type = "protan")
deutan <- dichromat(viridis_color, type = "deutan")
tritan <- dichromat(viridis_color, type = "tritan")

# plot for comparison
layout(matrix(1:4, nrow = 4)); par(mar = rep(1, 4))
recolorize::plotColorPalette(viridis_color, main = "Trichromacy")
recolorize::plotColorPalette(protan, main = "Protanopia")
recolorize::plotColorPalette(deutan, main = "Deutanopia")
recolorize::plotColorPalette(tritan, main = "Tritanopia")

3つくらいの要素であれば全然問題ないように思います。

penguin.png

library(palmerpenguins)

penguins %>% ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species))+
  geom_point(size = 2) +
  scale_color_viridis_d()

個人的な落としどころ

というのを経て、今のところ自分はggokabeitoパッケージを使うようにしています。これもTritanopiaの方からは判別が難しいように見えるのですが、以下の理由でとりあえずこれがベターかなと考えました。

  • viridisだと要素毎に分けていても連続的な印象を与えそう(要素が3つくらいだと問題無いとは思う)
    • これはデフォルトのhue_palも起こりえるかも
  • 一方okabe_itoでは連続的な印象は与えにくい
  • 個人的に黄色がviridisより見やすい

okabeito_penguin.png

okabe_7.png

当然、これを使っておけばOK、という訳ではないと思います。結局は、要素数を減らしたりshapeと組み合わせるなど、そもそもの工夫をしたうえでカラーパレットを選択すると思いますので、単純な話ではないなあ、というのが色々調べて思った感想です。

おまけ

ggplotのデフォルトのカラーパレットが循環しているということを確認しました。

> hue_color <- hue_pal()(10000) %>% unique()    #10000は適当なデカい数値
> length(hue_color)    #色は1176通りあるっぽいことが分かる
[1] 1176
> head(hue_color)
[1] "#F8766D" "#F8766C" "#F8776C" "#F7776B" "#F7776A" "#F77769"
> tail(hue_color)
[1] "#F97571" "#F97570" "#F87570" "#F87670" "#F8766F" "#F8766E"

こう見ると、#F8766Dから始まり#F8766Eで終わっているので、確かに循環しているっぽいです。
なので、試しにどんな感じで循環しているか可視化してみたところ、当たり前といえば当たり前ですが境目なくきれいに繋がっている事が確認できました。

circulation.png

サンプルコード
library(ggeasy)
library(xkcd)

rad <- seq(0, 2 * pi, length.out = 1176)

circle <- tibble(x = cos(rad),
                 y = sin(rad),
                 n = 1:1176)

circle %>%
  ggplot(aes(x = x, y = y, colour = factor(n))) +  #ここのfactorを外せばこんな変なグラフにはならない
  geom_point(size = 3) +
  easy_remove_legend() + 
  easy_labs(title = "circulation") +
  theme(text = element_text(size = 16, family = "xkcd"))

参考にしたもの

11
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?