cucumber flesh

Rを中心としたデータ分析・統計解析らへんの話題をしていくだけ

ggplot2のsizeが意味するもの

付け焼き刃な知識故に、間違いございましたら指摘頂けますと幸いです。

ggplot2を使っていると、数種類の“size”を設定するタイミングがある。例えば、geom_point()で散布図を描画する際のポイントの大きさを指定するためのsize、または連続した線を描画するのに用いられるgeom_line()でのsize、あるいは文字を重ねるためのgeom_text()annotate()の中でのsizeである。また、少し異なる引数名であるがテーマ指定の関数theme_*()にも“base_size”という名の引数が用意されている。ここで肝心なことは、テキストとその他では、同じsizeであっても単位が異なるということだ。このことは次のStackOverflowの投稿にまとめられている。

stackoverflow.com

まとめて書いてしまうとこの通り。

  • レイヤーとして重ねるgeom_point()geom_line()などの要素のサイズはmm単位(ポイントの大きさ、線の太さなど)
  • 軸やタイトルなど、フォントを表示するテキスト系のサイズはpoint単位(1pointsはおよそ0.352778mm)
  • geom_point()のポイントの輪郭の太さを制御するstrokeの単位もpoint(ggplot2::.stroke

以下、この記事ではそのことを確かめてみたいと思う。

適当なggオブジェクトを用意し、それに手を加えて比較していくことにする。

library(ggplot2)
# 日本語の表示のためにフォントを指定
theme_set(theme_gray(base_family = "IPAexGothic"))

p <- 
  ggplot(mtcars, aes(wt, mpg))

まずはgeom_point()geom_line()でのsizeである。ここではsize = 10を指定した(既定では1.5)。

p_out <- 
  p + 
  geom_point(size = 10)

この結果をggsave()で出力した図を表示する。ポイントのサイズが10mmにしたので、検証のために出力時のサイズはその10倍となる10cmとした。

ggsave(filename = "out.png", 
       plot = p_out, 
       width = 10, 
       height = 10, 
       units = "cm")

f:id:u_ribo:20180611230853p:plain

確かにmmらしい。もっとも、これはソースコードにも示されている。

Size examples Should be specified with a numerical value (in millimetres), or from a variable source

github.com

次に、軸やタイトルテキストのsizeである。軸のラベルを除いて、size = 10を指定した。

p2 <- 
  p_out +
  # 適当な場所に文字「A」を表示
  annotate("text", x = 2, y = 15, size = 10, label = "A", color = "red") +
  ggtitle("文字の大きさはpointで指定")

p2 + 
  theme(title = element_text(size = 10),
         axis.title = element_text(size = 10),
         # グラフの両軸に用いられる数値の大きさ
         axis.text = element_text(size = 5))

f:id:u_ribo:20180611231008p:plain

フォントを扱っていて、なおかつ同じsize = 10を指定していてもannotate()が表示するフォントが大きい。これはannotate()がレイヤーの要素として評価されるためで、geom_point()のようにsizeはmm単位での指定となるためだ。

もし、タイトルや軸のサイズをmm単位にしたい時はpointをmmへ変換する必要がある。ggplot2::.ptはggplot2の内部で用いられている変数で、ドキュメントもある

p2 +
  theme(axis.title = element_text(size = ggplot2::.pt * 10))

f:id:u_ribo:20180611231028p:plain

最後にtheme_*()の引数“base_size”だが、こちらも単位はpointである。すなわち次の2つのコードによって出力される図は等しい。

ggplot2が生成するような描画オブジェクトの差分を確認するにはvdiffrが便利である。ここではwidget_diff()を用いて差分の検証を行うが、GitHubのように2つの画像を表示し、スライドさせながら差分を確認するwidget_slide()やテスト時に役立つ関数も備わっている。

qiita.com

# plotとaxisのラベルの大きさは、テーマのbase_sizeに対してI()で指定した値をかけた大きさとなる
p_default <- 
  p2 + 
  theme_gray(base_size = 11,
             base_family = "IPAexGothic")

p_custom <- 
  p2 +
  theme_replace(
    plot.title = element_text(size = 11 * I(1.2)),
    axis.title = element_text(size = 11 * I(0.8)))
# 2つのオブジェクトで差分がない場合は白い画面が表示される
vdiffr::widget_diff(
  p_default,
  p_custom
)

# 変更してみる
# フォントサイズが変更されたことで全体の配置も微妙にずれる
vdiffr::widget_diff(
  p_default,
  p_custom +
    theme(plot.title = element_text(size = 20))
)

f:id:u_ribo:20180611231716p:plain

学術誌に投稿する図では、軸のテキストサイズやらについて細かく指定しされているものもある。怒られないように、少しずつggplot2に慣れていこうと思う。 Enjoy!