4  可視化のTips

この章では, データ可視化に関するいくつかのTipsを紹介します. しかし, これらのテクニックは次の一つの原則に基づいているに過ぎません.

Tip可視化の原則

図は主張をもち, その主張を最短時間で伝えられるようにデザインされなければならない.

これから紹介するテクニックは図の見た目を改善するためのものですが, それらは単に最短時間で図の主張を伝えるために手段であると言うことを忘れないでください.

library(dplyr)
library(ggplot2)

4.1 最少の要素

最短時間で図を伝えるためには, 過剰な情報を削ぎ落とすことが重要です. これを表した Tufte (2001) の有名な原則があります.

Tipデータインク比の原則 (Tufte 2001)

図においては次のデータインク比を最大化しなければならない:

\[ \text{データインク比} := \frac{\text{データインク}}{\text{図に使用されたインクの総量}}. \]

ここでいうデータインクとは, 図の中でデータを表すために使われているインクの量のことであり, 基本的には図を構成するために最低限必要な要素のことを指します. ここから, 次のような規則も見出すことができます:

Tipデータインク比の原則の系

削除しても図の主張を損なわない要素は削除しなければならない.

この原則を, R に標準で付属する penguins データセットで確かめてみましょう. ここではペンギンの種 (species) ごとに, 性別 (sex) 別の個体数を数えた棒グラフを描きます. まずは何の工夫もしていない, デフォルトのグラフです.

penguins_bar <- penguins |>
  filter(!is.na(sex))

penguins_bar |>
  ggplot(aes(x = species, fill = sex)) +
  geom_bar(position = "dodge")

このグラフには

  • グレーの背景
  • 縦横のグリッド線
  • 自明な軸ラベル

など, データを表していないインクが多く含まれています. データインク比の原則に従って, これらの要素を削ぎ落とします.

penguins_bar |>
  ggplot(aes(x = species, fill = sex)) +
  geom_bar(position = "dodge") +
  labs(
    x = NULL,
    y = NULL,
    fill = NULL,
    title = "Number of Penguins by Species and Sex"
  ) +
  theme_minimal() +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major.x = element_blank()
  )

さらに可読性を高めるために, 棒を横向きにして凡例をパネル内の空白に移します. 横向きにするとカテゴリ名が水平に並ぶので, ラベルが長くなっても読みやすくなります. また, 凡例をパネル内の空白に移すことで, グラフ全体のバランスが良くなります.

penguins_bar |>
  ggplot(aes(x = forcats::fct_rev(species), fill = sex)) +
  geom_bar(position = "dodge") +
  coord_flip() +
  labs(
    x = NULL,
    y = NULL,
    fill = NULL,
    title = "Number of Penguins by Species and Sex"
  ) +
  theme_minimal() +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major.y = element_blank(),
    legend.position = "inside",
    legend.position.inside = c(0.9, 0.15),
    plot.title.position = "plot"
  ) +
  guides(fill = guide_legend(reverse = TRUE))

なお, 横向きに変えたことに伴って見づらくなってしまった点があるので

  • forcats::fct_rev() 関数を使ってカテゴリの順番を逆にしています
  • guides(fill = guide_legend(reverse = TRUE)) を使って, 凡例の順番も逆にしています

4.2 色の選び方

色の選択は重要なテーマで様々な理論がありますが, ここでは深入りせずに用意されているカラーパレットを紹介します.

R Color Brewer’s Palettes

現代的なカラーパレット集として有名な Color Brewer のパッケージとして, RColorBrewerが提供されています.

penguins_bar |>
  ggplot(aes(x = forcats::fct_rev(species), fill = sex)) +
  geom_bar(position = "dodge") +
  coord_flip() +
  labs(
    x = NULL,
    y = NULL,
    fill = NULL,
    title = "Number of Penguins by Species and Sex"
  ) +
  scale_fill_brewer(palette = "Set2") +
  theme_minimal() +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major.y = element_blank(),
    legend.position = "inside",
    legend.position.inside = c(0.9, 0.15),
    plot.title.position = "plot"
  ) +
  guides(fill = guide_legend(reverse = TRUE))

カラー・セーフティ: Okabe-Ito パレット

色選択の一つの方針として, 色覚異常の人でも見分けやすい色を使う, という考え方があります. カラー・セーフティなパレットとして提案された中でも有名なカラーパレットがOkabe-Itoカラーパレットです.

penguins_bar |>
  ggplot(aes(x = forcats::fct_rev(species), fill = sex)) +
  geom_bar(position = "dodge") +
  coord_flip() +
  labs(
    x = NULL,
    y = NULL,
    fill = NULL,
    title = "Number of Penguins by Species and Sex"
  ) +
  see::scale_fill_okabeito() +
  theme_minimal() +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major.y = element_blank(),
    legend.position = "inside",
    legend.position.inside = c(0.9, 0.15),
    plot.title.position = "plot"
  ) +
  guides(fill = guide_legend(reverse = TRUE))

MetBrewer パレット

MetBrewer は, アメリカのメトロポリタン美術館のコレクションからインスピレーションを得たカラーパレットを提供するパッケージです.

# install.packages("MetBrewer")
library(MetBrewer)

ここでは Kandinsky のパレットを使ってみましょう.

penguins_bar |>
  ggplot(aes(x = forcats::fct_rev(species), fill = sex)) +
  geom_bar(position = "dodge") +
  coord_flip() +
  labs(
    x = NULL,
    y = NULL,
    fill = NULL,
    title = "Number of Penguins by Species and Sex"
  ) +
  scale_fill_manual(values = met.brewer("Kandinsky")) +
  theme_minimal() +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major.y = element_blank(),
    legend.position = "inside",
    legend.position.inside = c(0.9, 0.15),
    plot.title.position = "plot"
  ) +
  guides(fill = guide_legend(reverse = TRUE))

4.3 フォント

フォントの種類

フォントには大きく分けて, セリフ体 (serif) とサンセリフ体 (sans-serif) の二種類があります. セリフ体は文字の端に装飾があるフォントで, サンセリフ体は装飾のないフォントです. 下の左の図で赤く示された, 文字の端の突起や飾りが「セリフ」です.

セリフ体 (serif)

セリフ体 (serif)

サンセリフ体 (sans-serif)

サンセリフ体 (sans-serif)

日本語でも明朝体がセリフ体でゴシック体がサンセリフ体に相当します. 英語では, セリフ体は Times New Roman や Garamond などが有名で, サンセリフ体は Arial や Helvetica などが有名です.

フォントの選び方

基本的に図表はサンセリフ体を使うことが推奨されます. これは, サンセリフ体の方が小さいサイズでも読みやすいからです. ggplot2 では, デフォルトでサンセリフ体 (多くの場合のシステムに入っている Helvetica か Arial) が使われています.

ただし, 日本語でラベルを追加しようと思うと, Helvetica や Arial には日本語が含まれていないため, 日本語が豆腐化 (□) してしまいます. 日本語を表示するためには, 日本語が含まれているフォントを指定する必要があります. 例えば, Windows では Meiryo, Mac では Hiragino Kaku Gothic ProN などが日本語を含むサンセリフ体のフォントとしてよく使われます.

日本語フォントの解決法

一つの問題として, PC間でコードを共有した場合に, フォントが入っていないと言う問題が起きます. 特にMacのヒラギノ系は有料フォントであるため, Macユーザ以外が持っていることは想定しないほうが良いです. これらの問題をシンプルに解決するのが, showtext パッケージです. showtext を使うことでフォント周りの問題をコード上で完結させることができます.

# install.packages("showtext")
library(showtext)

font_add_google("Noto Sans JP") # Google Fonts から Noto Sans JP フォントを追加
showtext_auto() # フォントの自動使用を有効化
penguins_bar |>
  mutate(
    species = recode(
      species,
      "Adelie" = "アデリー",
      "Chinstrap" = "ヒゲ",
      "Gentoo" = "ジェンツー"
    ),
    sex = recode(
      sex,
      "male" = "オス",
      "female" = "メス"
    )
  ) |>
  ggplot(aes(x = forcats::fct_rev(species), fill = sex)) +
  geom_bar(position = "dodge") +
  coord_flip() +
  labs(
    x = NULL,
    y = NULL,
    fill = NULL,
    title = "ペンギンの種と性別ごとの個体数"
  ) +
  scale_fill_manual(values = met.brewer("Kandinsky")) +
  theme_minimal(base_family = "Noto Sans JP") +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major.y = element_blank(),
    legend.position = "inside",
    legend.position.inside = c(0.9, 0.15),
    plot.title.position = "plot"
  ) +
  guides(fill = guide_legend(reverse = TRUE))

4.4 画像形式

レポートやスライドに図を載せる場合, 画像形式の選択が見栄えに影響を与えます. ここでは画像形式について最低限知っておくべきことを紹介します.

ラスターとベクター

画像形式には大きく分けて, ラスター (raster) 形式とベクター (vector) 形式があります. ラスター形式はピクセルで構成される画像で, 解像度に依存します. 一方, ベクター形式は数式で描画されるため, 拡大しても画質が劣化しません.

この違いは, 同じ図を拡大してみると一目瞭然です. 例として, シンプルなサインカーブを描いてみましょう.

df_sine <- tibble::tibble(
  x = seq(0, 2 * pi, length.out = 300),
  y = sin(x)
)

p_sine <- df_sine |>
  ggplot(aes(x = x, y = y)) +
  geom_line(color = "#0072B2", linewidth = 1) +
  labs(x = "x", y = "sin(x)") +
  theme_minimal() +
  theme(panel.grid.minor = element_blank())

p_sine
Figure 4.1: A sine curve.

このサインカーブの山の部分を, 低解像度のラスター形式 (PNG) とベクター形式 (SVG) で保存し, それぞれ大きく引き伸ばして並べたものが下の図です.

p_zoom <- p_sine +
  coord_cartesian(xlim = c(pi / 2 - 1, pi / 2 + 1), ylim = c(0.5, 1.02)) +
  labs(x = NULL, y = NULL)

p_zoom
p_zoom
Figure 4.2: Raster (PNG)
Figure 4.3: Vector (SVG)

ラスター形式では拡大に伴ってピクセルのギザギザ (ジャギー) が目立つのに対し, ベクター形式では曲線が滑らかなまま保たれています.

皆さんが知っておくべき画像形式は次の4つです:

ラスター

ベクター

知っておくべき画像形式は SVG と PDF です.

SVG (Scalable Vector Graphics) はWeb 上で使われるベクター形式の画像です. Web ブラウザで表示することができ, 拡大しても画質が劣化しません. また, SVG は XML 形式で記述されるため, テキストエディタで編集することも可能です.

PDF (Portable Document Format) は, Adobe が開発したベクター形式の画像です. PDF は印刷に適しており, 拡大しても画質が劣化しません. また, PDF は多くのアプリケーションでサポートされており, 共有や印刷に便利です.

画像形式の選び方