R {ggplot2} で 少し複雑なサブプロットが描きたい
この記事は R Advent Calendar 2015 4 日目の記事です。
{ggplot2}
でのサブプロット
{ggplot2}
でサブプロットを描画したいことがある。同じ種類のプロットを水準別に描画するなど、単純なものであれば facet
で描ける。例えば 適当な散布図を Species
別に描きたい場合、
library(dplyr) library(ggplot2) ggplot(iris, aes(Sepal.Width, Sepal.Length)) + geom_point() + facet_wrap(~ Species)
facet
では異なる種類のプロットをサブプロットとすることはできない。例えば散布図の縦軸/横軸をそれぞれ変えたい、といった場合には gridExtra::grid.arrange
を使う。
library(gridExtra) p1 <- ggplot(iris, aes(Sepal.Width, Sepal.Length)) + geom_point() p2 <- ggplot(iris, aes(Petal.Width, Petal.Length)) + geom_point() p3 <- ggplot(iris, aes(Sepal.Length, Petal.Length)) + geom_point() p4 <- ggplot(iris, aes(Sepal.Width, Petal.Width)) + geom_point() grid.arrange(p1, p2, p3, p4)
が、grid.arrange
は引数を ドット ...
で受け取ること、また呼び出すと直ちに描画を行うことから、以下のような場合は少し面倒だ。
- 描画が直ちに行われるため、サブプロットの描画設定をまとめて変更できない。単一のテーマを使う場合でも、個々のプロットそれぞれについてあらかじめ処理を行っておく必要がある。
- リストが渡せない。サブプロットの数を動的に変更したい場合は、リストに入れて
do.call
が必要である。
というわけで、自作パッケージ {ggfortify}
でこの辺の操作を少し便利にできるようにした。サブプロット周りの処理は ggmultiplot
クラスで行う。
コンストラクタの引数にはリストが渡せるため、サブプロット数が変わる場合でも楽だと思う。また、インスタンスに対して +
演算子を用いることで ggplot
と同じ処理を各プロットに対して適用できる。
# install.packages('ggfortify') library(ggfortify) p <- new('ggmultiplot', plots = list(p1, p2, p3, p4)) p # 略。上記 grid.arrange と同じ出力 # theme_bw を全サブプロットに適用 p + theme_bw()
サブプロットの要素には リストと同じようにアクセスできる。[
でのアクセスは ggmultiplot
インスタンスに、[[
での アクセスは ggplot
インスタンスになる。代入もできるため、一部のプロットにだけ処理を適用したい場合は以下のように書ける。
p[2:3] <- p[2:3] + stat_smooth(method = 'lm') p
+
演算子の右項に ggplot
インスタンスを指定するとサブプロットが追加できる。
p + (ggplot(iris, aes(Sepal.Width, fill = Species)) + geom_density())
ggmultiplot
作成時に ncol
もしくは nrow
キーワードを指定することで、サブプロットの列数 / 行数が指定できる。
p <- new('ggmultiplot', plots = list(p1, p2, p3, p4), ncol = 3) p
autoplot
との組み合わせ
{ggfortify}
を使うと主要なクラスを ggplot2::autoplot
関数で描画できるようになる。autoplot
にリストを渡した場合は、リストの各要素が autoplot
可能であればそれらをサブプロットとして描画する。
サンプルとして、{broom}
パッケージの vignettes にある例をやってみたい。ここでは、適当なデータに対して クラスタ数を変えながら kmeans
クラスタリングを行った結果をプロットしている。
これは autoplot
を使って以下のように書ける。
kclusts <- data.frame(k=1:9) %>% dplyr::group_by(k) %>% dplyr::do(kclust = kmeans(iris[-5], .$k)) autoplot(kclusts$kclust, data = iris[-5], ncol = 3) + theme(legend.position = "none")
一行目は今なら {purrr}
を使ったほうが簡潔でわかりやすくなると思う。
library(purrr) kclusts <- purrr::map(1:9, ~ kmeans(iris[-5], .)) autoplot(kclusts, data = iris[-5], ncol = 3) + theme(legend.position = "none") # 略
まとめ
{ggfortify}
では ggmultiplot
クラス、ならびに autoplot
を利用してサブプロットを簡単に扱うことができる。
Rグラフィックスクックブック ―ggplot2によるグラフ作成のレシピ集
- 作者: Winston Chang,石井弓美子,河内崇,瀬戸山雅人,古畠敦
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/11/30
- メディア: 大型本
- この商品を含むブログ (2件) を見る