ggplot2でグラフを作っているときに困ること
ggplot2を用いてR上で作図を行っていると
- なんかデフォルトだとx軸とy軸見えないから書き込みたいな
- 背景を灰色じゃなくて白にしたい!
- x軸のタイトルを消して、x軸のラベルをななめ書きにしたいな…
などのグラフの見た目に関わる変更を行いたいときがあると思います。
しかし、このような変更をどのようなコードで実行すればよいのかわからず困るかもしれません。
そんな時には…
themeで軸の書き込み!
# Before
ggplot(iris, aes(x = Sepal.Length, Sepal.Width, color = Species)) + geom_point()
# After
ggplot(iris, aes(x = Sepal.Length, Sepal.Width, color = Species)) + geom_point() +
theme(axis.line = element_line(color = "black"))
Before | After |
---|---|
themeで背景の変更!
# Before
ggplot(iris, aes(x = Sepal.Length, Sepal.Width, color = Species)) + geom_point()
# After
ggplot(iris, aes(x = Sepal.Length, Sepal.Width, color = Species)) + geom_point() +
theme(panel.background = element_blank())
Before | After |
---|---|
themeでx軸の編集!
# Before
ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) + geom_boxplot()
# After
ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) + geom_boxplot() +
theme(
axis.title = element_blank(),
axis.text.x = element_text(size = 15, angle = -30, vjust = 0.5, hjust = 0)
)
Before | After |
---|---|
こんなふうにtheme
関数を用いると、希望通りに見た目をいい感じにコントロールできます。
ggplot2におけるthemeとは何か
ggplot2を用いる場合に限らず、Rで作図を行っていると、ラベルや軸の表現の仕方などの調整を行いたくなる場合があります。
ggplot2でこのような変更を行いたい際に出てくるのがtheme
関数です。この関数を用いて設定を行うことでレイアウトを調整することができます。
ではtheme
関数とは何なのでしょうか?公式のレファレンスにはこのように書いてありました。
Themes are a powerful way to customize the non-data components of your plots: i.e. titles, labels, fonts, background, gridlines, and legends.
テーマとは、あなたのプロットのデータではない構成要素(例えば、タイトル、ラベル、フォント、背景、罫線、凡例)をカスタマイズするための強力な手段である(拙訳)
そう、つまりtheme
とはggplotにおいてgeom_
関数などでは操作できない見た目の部分をコントロールするための関数なのです。
しかし、レファレンスなどを見ても設定できる項目が膨大で、使いこなすのは大変そうに見えます。けれど冒頭に示した通り、少しでも使いこなせたら絶対に便利!
そこでここでは自分の勉強もかねて、theme
の使い方をまとめてみようと思います。
以下のページなどを参考にしました。
※ 以下のコードを実行するにはggplot2パッケージが必要です(library(ggplot2)
で読み込んでください)
※ プロットの際に警告が出ますが、見た目の確認には問題ありません
theme
を使うにあたって知っておいたら良さそうな3項目!
theme
を扱う際にこれだけ抑えておければいいかな、と思ったポイントが以下の3つです。
1. 引数名は住所みたいになっているので、コントロールしたい部分に対応する引数名を選べばよい
2. 構成要素のコントロールは基本的にelement_
関数で行う
3. 作成したテーマは保存して使いまわせる
ここではこの3項目に沿って、例を交えながらtheme
の使い方を見ていきます。
1. 引数名は住所みたいになっているので、コントロールしたい部分に対応する引数名を選べばよい
theme
のレファレンスを見ていただければわかるのですが、theme
がとる引数の名前は単語が「.」をはさんで連続する形になっています。
例えば、短いとtext
、長くなるとaxis.text.x
のようになります。
これの仕組みは簡単で、***「コントロールしたい構成要素に対応してそうな引数名を選んで設定を指定すれば、そのように見た目が変更される」***だけです。
たとえば以下の図
g1 <- ggplot(msleep, aes(x = sleep_total, y = sleep_rem, color = vore)) + geom_point()
plot(g1)
でtext
(グラフ上のすべてのテキスト)を(後述する方法で)描画しないように設定してみると…
g2 <- g1 + theme(text = element_blank())
plot(g2)
ことごとくすべての文字が消えます。
一方で、axis.text.x
(x軸上の文字)を描画しないように設定してみると…
g3 <- g1 + theme(axis.text.x = element_blank())
plot(g3)
このようにx軸の目盛の数値だけが消えます。
もう一例見てみると、例えばpanel.grid
(描画領域内のグリッド線)とpanel.grid.minor.x
(x軸に垂直な小目盛りのグリッド線)の場合…
panel.grid
をコントロールすると…
g4 <- g1 + theme(panel.grid = element_line(color = "red", size = 2))
plot(g4)
panel.grid.minor.x
をコントロールすると…
g5 <- g1 + theme(panel.grid.minor.x = element_line(color = "red", size = 2))
plot(g5)
のようになります。
厳密に引数に階層性がある訳ではないのですが、基本的に上位の構成要素について設定を行うと下位の構成要素はそれに従います。よって、***「大まかに指定したいときには大まかな引数を、細かく指定したいときには細かい引数を」***でいい感じに調整できると思います。
対応する引数名はどうやって探すか?
個人的にはtheme
関数のレファレンスのなかから探すのがよいと思います。
ブラウザ上でCtrl+Fを使って関連がありそうな言葉から探すのもありですし、「axis」や「legend」などの言葉をもとに探してみるのもありです。
そこまでわかりにくい名づけにはなっていないので、すぐに目当ての引数を見つけられると思います。
引数名の一例 from https://ggplot2.tidyverse.org/reference/theme.html
2. 構成要素のコントロールは基本的にelement_*
関数で行う
theme
関数の場合、引数に渡すのは基本的にelement_*
関数というものであり、これで該当箇所のレイアウトをコントロールすることになります。
element_*
関数には、element_blank
、element_rect
、element_line
、element_text
の4つがあります。
element_blank
:「何もない」を指定(=消す)
グラフ上の何かの構成要素を消したい場合にはelement_blank
を使います。
たとえば、軸上の目盛りの目印(axis.ticks
)と凡例のタイトル(legend.title
)と描画領域の背景(panel.background
)を消したい場合は以下のようになります。
g6 <- g1 + theme(
axis.ticks = element_blank(),
legend.title = element_blank(),
panel.background = element_blank()
)
plot(g6)
とりあえず消したいときにはelement_blank
です。
ちなみにpanel.background
や後述するplot.background
に対してelement_blanck()
を指定してベクタに出力すると、これらの領域を透過背景にすることができるようです。逆に言うと確実に白色背景にしたい場合にはelement_blank
は適さないかもしれません。
element_rect
:境界と背景のコントロール
境界や背景(ようするに四角いもの)をコントロールしたい際にはelement_rect
を使います。
たとえば、描画領域の背景(panel.background
)や凡例の点の背景(legend.key
)をコントロールしたい場合には
g7 <- g1 + theme(
panel.background = element_rect(fill = "#e9e4d4", color = "black", linetype = 4, size = 2),
legend.key = element_rect(fill = "#e9e4d4", color = "black")
)
plot(g7)
のようになります。
※ ただし、panel.background
とpanel.border
の設定には少し注意が必要なようです(詳しくは前掲したこちらのページを参照してください)
element_line
:線のコントロール
線全般のコントロールはelement_line
で行います。
たとえば、x、y軸の線(axis.line
)や軸上の目盛りの目印(axis.ticks
)、描画領域内のグリッド線(panel.grid.major
)、描画領域内の小グリッド線(panel.grid.minor
)をコントロールしたい場合には以下のようになります。
g8 <- g1 + theme(
axis.line = element_line(arrow = arrow()),
axis.ticks = element_line(color = "red", size = 2),
panel.grid.major = element_line(color = "pink"), panel.grid.minor = element_blank()
)
plot(g8)
element_text
:テキストのコントロール
テキスト全般のコントロールはelement_text
で行います。もちろん、文字の回転、フォント指定などもできます。
たとえば、x軸タイトル(axis.title.x
)、y軸タイトル(axis.title.y
)、y軸上のテキスト(axis.text.y
)をコントロールしたい場合には以下のようになります。
g9 <- g1 + theme(
axis.title.x = element_text(family = "serif", face = "bold", size = 20),
axis.title.y = element_text(family = "serif", face = "bold", size = 20, angle = -90),
axis.text.y = element_text(angle = -90, size = 15, hjust = 0.5)
)
plot(g9)
その他のelement_*
関数の詳しい使い方についてはレファレンスにのっています。
3.作成したテーマは保存して使いまわせる
上記のように、theme
を用いればプロットの見た目を様々に変えることができます。
さらに、自分が作成したテーマはオブジェクトに保存することで何回でも使いまわすことができます。
たとえば以下のようにテーマを作成して
# テーマの保存
theme_new <- theme(
# 背景を消す
panel.background = element_rect(fill = "white", color = "black"),
# 凡例の設定
legend.position = c(0.15, 0.85),
legend.title = element_blank(),
legend.text = element_text(size = 15),
legend.key = element_blank(),
# テキスト形式の設定
axis.title.x = element_text(family = "serif", face = "bold", size = 20),
axis.title.y = element_text(family = "serif", face = "bold", size = 20, angle = -90),
axis.text.x = element_text(angle = 0, size = 15, hjust = 0.5),
axis.text.y = element_text(angle = -90, size = 15, hjust = 0.5)
)
あるプロットで呼び出すと
h1 <- ggplot(msleep, aes(x = sleep_total, y = sleep_rem, color = vore)) +
geom_point(size = 2) + theme_new
plot(h1)
別のプロットで呼び出すと
h2 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_point(size = 2) + theme_new
plot(h2)
このように、別々のプロットでも同様の見た目に調整することができます。
その他のTips
上記の3項目でおおまかには使い方をカバーできると思うのですが、以下を使うとさらに見た目をコントロールすることができます。
凡例のコントロール
先ほどのtheme_new
ですでに使ってしまっているのですが、凡例は位置などをtheme
でコントロールすることができます。
※ ただし、色分けなどについては後述するscale系の関数で行う必要あり
g1 + theme(
legend.direction = "horizontal",
legend.position = c(0.35, 0.95),
legend.background = element_blank(),
legend.title = element_text(size = 15)
)
追記:凡例を消す場合
凡例を消したい場合、特にすべての凡例を消したい場合には、legend.position
に"none"
を指定することで凡例を消すことができます。
ただし一部の凡例のみを消したい場合には、guides
関数や対応するscale_*
関数で特定の凡例を指定して消す必要があります。
# そのまま
ggplot(msleep, aes(x = sleep_total, y = sleep_rem, color = vore, shape = conservation)) +
geom_point()
# すべての凡例を消す
ggplot(msleep, aes(x = sleep_total, y = sleep_rem, color = vore, shape = conservation)) +
geom_point() + theme(legend.position = "none")
# 一部の凡例を消すやり方①
ggplot(msleep, aes(x = sleep_total, y = sleep_rem, color = vore, shape = conservation)) +
geom_point() + guides(color = "none") # `shape = "none"にすればshapeの凡例が消える
# 一部の凡例を消す やり方②
ggplot(msleep, aes(x = sleep_total, y = sleep_rem, color = vore, shape = conservation)) +
geom_point() + scale_shape_discrete(guide = "none") # scale_color_discrete(guide = "none")にすればcolorの凡例が消える
そのまま | すべて消す | やり方① | やり方② |
---|---|---|---|
参考
長さのコントロール
unit
関数を使用することで、長さ、大きさを一部の引数に対して直接指定することができます。
※ unit
については勉強中のため、ここでは見た目がいい感じになるように単位をcmにして適宜設定しています(実際に使う際にもそれが手っ取り早いかも?)
ggplot(msleep, aes(x = sleep_total, y = sleep_rem, color = vore, shape = conservation)) +
geom_point(size = 3) +
theme(axis.ticks.length = unit(0.5, "cm"), legend.key.width = unit(3.5, "cm"))
ビルトインテーマ
またggplot2には、すでにいい感じにパラメータの設定がなされた、ビルトインのテーマが複数あります(ggplotのthemeの話ではむしろこっちの方がよく出てくるかもしれません)。
簡便に見た目を変更したい場合などにこれらは非常に有用です。
theme_grey() | theme_bw() | theme_linedraw() | theme_light() |
---|---|---|---|
theme_dark() | theme_minimal() | theme_classic() | theme_void() |
---|---|---|---|
詳しくはこちらなどから |
注意点
このようにtheme
関数は見た目のコントロールを行うのに非常に強力なツールなのですが、以下のような注意点もあります。
###「データが関わる部分」はコントロールできない
少しわかりにくい表現なのですが、theme
関数では「データが関わる部分」をコントロールできません。つまり紙の上の点を移動させるようなレイアウト操作ができません。
これらの「紙の上ではどこにどのようにデータが描画されるか」という部分については、geom_*
関数やScale関連の関数でコントロールする必要があります。
たとえばプロットする範囲を動かしたい場合はxlim
やylim
を使う、対数軸にしたい場合はscale_*_log10()
を使う、目盛りの区切り数を変えたい場合はscale_:_continuous
を使う、などのようにtheme
関数の適用前に調整を行う必要があります。
theme_tmp <- theme_new +
theme(
panel.grid.major.x = element_line(color = "black"),
panel.grid.minor.x = element_line(color = "grey")
)
# Scaleの設定なし
g1.no_scale <- g1 + theme_tmp
plot(g1.no_scale)
# Scaleの設定あり
g1.with_scale <- g1 + scale_x_continuous(breaks = seq(0, 20, 2), minor_breaks = seq(0, 20, 1)) + theme_tmp
plot(g1.with_scale)
Scaleの設定なし | Scaleの設定あり |
---|---|
余白の設定は結構難しいかも
theme
をいじくるとわかってくるのですが、ggplotのプロット領域は実際にデータが描画される「panel領域(下図青色)」とその周囲も含む領域である「plot領域(下図青色+赤色)」に分かれています。
g1 + theme(
panel.background = element_rect(fill = "#2a83a2"),
plot.background = element_rect(fill = "#e95464")
)
よって、panel.*
の引数はpanel領域を、plot.*
の引数は(おそらくレイヤ的には下になるため)その外側をコントロールするものということになります。
つまりこの領域の設定をいじればプロットの余白を変えられるのですが、margin
関数の引数を微調整しながら変更していく必要があるため「panel領域だけ切り抜く」というのをコード上で行おうとすると結構難しいかもしれません。
たとえば以下のように設定して、自分の環境で出力すると下図のようになります。
g1.margin <- g1 + theme(
panel.background = element_rect(fill = "#2a83a2"),
plot.background = element_rect(fill = "#e95464"),
plot.margin = margin(1, -3, 0, -1, "cm")
)
ggsave(g1.margin, file = "g1.margin.png", width = 7, height = 7)
余白コントロールの参考
まとめ:themeの使い方が分かればきっと便利!
このように、theme
関数は非常に便利な関数です。
このような機能もあるため、ggplotではRのデフォルトのplotに比べて見た目の変更が格段に行いやすいと思います。
自分もまだ不慣れで、つたない説明だったと思いますが、グラフ作成の際のお役に立てたら幸いです!
(年末にグラフをたくさん描くみなさまがんばってください!)