正確には+.gg
この記事の続き?かな。
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
以外にも実はtheme
もgg
を持っているんですね。
class(theme_bw()) ## [1] "theme" "gg"
ggplot2のほかの部品についても見てみます。
geom
やstat
はご存知の通り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~~