niszetの日記

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

(R) ggplot2パッケージの+の話

正確には+.gg

この記事の続き?かな。

niszet.hatenablog.com

ggplot2パッケージではレイヤーを足していくということで、+のオペレータがggオブジェクトに対して定義されています

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>

こんな感じに。

↑のコードを見ると気づきますが、ggのclassを持つものとしてggplot以外にも実はthemeggを持っているんですね。

class(theme_bw())
## [1] "theme" "gg"   

ggplot2のほかの部品についても見てみます。

geomstatはご存知の通りLayerで、

class(stat_bin())
## [1] "LayerInstance" "Layer"         "ggproto"      
class(geom_point())
## [1] "LayerInstance" "Layer"         "ggproto"      

などとなります。

scaleはちょっと特殊ですが、基本はScaleとその発展形。

 class(scale_x_log10())
## [1] "ScaleContinuousPosition" "ScaleContinuous"         "Scale"                  
## [4] "ggproto"    

coordもちょっと複雑ですがScaleと同様、

class(coord_equal())
[1] "CoordFixed"     "CoordCartesian" "Coord"          "ggproto"       

xlabなどは

class(xlab("x"))
## [1] "labels"

となっています。こうしてみると、結構色々なclassがありますねぇ。

gg以外足せない

本題に戻りますが、ggplot2パッケージ内ではggクラスにのみ+が定義されています。

これは例えばgeomを足しておこうと思って以下のように書くとエラーになります。

geom_line()+geom_point()
## Error in geom_line() + geom_point() : 
##   non-numeric argument to binary operator

まぁそりゃそうだ。+はLayer用には定義されていないのですから。

これについては先の記事にあるように、list()で囲う(listにする)と良いです。

+の中身を見てみると、e1はthemeかggplotでないといけないことがわかります。逆順にしてはいけないわけです。

# こんなこと普通しないけど
geom_point()+ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width))
## NULL

と、e1がthemeでもないしggpplotでもない(Layer)なので、スルーされてしまい、NULLが返ってきます。
themeも同様。

geom_point()+theme_bw()
## NULL

なお、左辺がthemeの場合は右辺はthemeしか足せません。

theme_bw()+geom_abline()
## Error: Don't know how to add RHS to a theme object

View(theme_bw())などで見てみるとわかりますが、themeはただのlist(がS3 classとして扱われている、いわゆる普通のS3)なので、ggprotoのとそれとは異なります。

ひとつ注意なのが、themeの場合は右辺がlistであってもダメということです。つまり、

theme_bw()+list(theme_dark())
## Error: Don't know how to add RHS to a theme object

です。themeの場合はthemeのまま足してあげましょう。

ggplot2パッケージの+の正確な挙動はマニュアルを参照してください。

Add components to a plot — +.gg • ggplot2

あとはソース読んだ方が早いかも…(大体書いた…けど、unevalだけちょっと特殊かな。気が向いたら、いつか)

Enjoy~~