niszetの日記

アナログCMOS系雑用エンジニアが頑張る備忘録系日記

(R) ggplot2で複数のレイヤーをlistにして一気に足す

ggbode中でも使っていますが…

まぁ見た方が早いと思うので。これが

library(ggplot2)
ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width,color=Species))+list(geom_line(),geom_point())

こうなる。

f:id:niszet:20180415181914p:plain

解説。

ggplot2パッケージでは+によりレイヤーを重ねたり、軸の設定をしたりしてどんどんと設定を追加していくことが出来ます。この内部の実装を見てみると、

ggplot2:::`+.gg`
## function (e1, e2) 
## {
##     e2name <- deparse(substitute(e2))
##     if (is.theme(e1)) 
##         add_theme(e1, e2, e2name)
##     else if (is.ggplot(e1)) 
##         add_ggplot(e1, e2, e2name)
## }
## <environment: namespace:ggplot2>

となっていて、+の左辺がggplotオブジェクトの場合、add_ggplot()が呼ばれています。で、その中身を見てみると、

ggplot2:::add_ggplot
## 抜粋
##     else if (is.list(object)) {
##         for (o in object) {
##             p <- p %+% o
##         }
##     }

となっていて、つまりlistで渡せばその要素に対してそれぞれ+の操作をしてくれる、というわけですね。

なお、先の例のlist()c()で置き換えられます。つまり

ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width,color=Species))+c(geom_line(),geom_point())

でも同じ結果が得られます。これは、geom_*というよりはLayerのオブジェクトのベクトルを作ることが出来ないからで、実際に

is.list(c(geom_line(),geom_point()))
## [1] TRUE
class(c(geom_line(),geom_point()))
## [1] "list"

であることを確認できます。ベクトルは(多分)アトミックな型(integer, numeric, raw, character, complex, logical)しか作れないのだと思います。どこかに書いてありそうだけど…

+は調べてみると面白かったので時間があれば何か書く、かも。

追記

一応、ヘルプを読むと

You can also supply a list, in which case each element of the list will be added in turn.

とあって、書いてあるもんだなぁ…と。

Add components to a plot — +.gg • ggplot2

Enjoy!!