11

The + usually throws non-numeric argument to binary operator when provided with something other than a number. But it works with ggplot2, pasting the plot together. At the same time, it retains its usual function outside of the context of ggplot2 (e.g. as an arithmetic or formula operator), so its ggplot2 version is not in conflict with either of these.

I wish to understand how to make the + behave this way. Browsing the ggplot2 github repo, I have found function definitions for +.gg and %+% but it did not make things clearer for me.

I would be happy with a pointer to the code in ggplot2 package that does this, or a generalized explanation of how this is done.

jakub
  • 4,774
  • 4
  • 29
  • 46

1 Answers1

12

If you dissect +.gg we have:

> 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)
}

Besides, add_theme, what you're interested in is is add_ggplot which can be accessed with ggplot2:::add_ggplot. The latter - a long yet very organized function - reveals more "cascading" functions to dispatch what's meant to be added.

That being said, R "knows" when using "+" on an object of class gg which function to apply (because of S3 classes). You can find the starting point in ggplot2 GitHub repos, in the ggproto.R on which I think most of ggplot2 behaviour depends on.

Is that what you're looking for?

Vincent Bonhomme
  • 7,235
  • 2
  • 27
  • 38
  • 1
    Thanks. What is not clear to me is that the name of the function is `+.gg`, but we don't use `+.gg`, we use simple `+`. How does R know to call `+.gg`, if that is what's happening? – jakub Nov 06 '16 at 15:25
  • 2
    That's because of [S3 classes](http://adv-r.had.co.nz/S3.html). And anything being a function call in R (try `+` (with quotes)), `ggplot2` "simply" extends the `+` method to object of class `gg`. – Vincent Bonhomme Nov 06 '16 at 15:27
  • Hmm, seeing the `.` in there now, this should have pointed me in the right direction! Would you happen to know where the definition of the class is in the ggplot2 repo? – jakub Nov 06 '16 at 15:29
  • you mean the `gg` class or the `+.gg` method? – Vincent Bonhomme Nov 06 '16 at 15:31
  • The class. It does not appear to be in the [same file](https://github.com/tidyverse/ggplot2/blob/master/R/plot-construction.r) as the method. – jakub Nov 06 '16 at 15:37
  • I think most of it relies on [`ggproto`](https://github.com/tidyverse/ggplot2/blob/master/R/ggproto.r) but not 100% sure. – Vincent Bonhomme Nov 06 '16 at 15:41
  • I've been stressing over this all day :-) Thanks to both the question and the answer. Coming from other languages, I tried looking for "operator overloading" initially, but that went nowhere, perhaps since it's considered a different concept. I think the linked "S3 Classes" document is exactly what I'm looking for. – Mike M Aug 22 '20 at 17:23
  • If I define `(backtick)+.character(backtick) <- paste0`, `'a'+'b'` doesn't work. Why is it so? – chan1142 Nov 11 '21 at 13:30
  • 1
    @chan1142 This is because operators like `+` only dispatch s3 on objects with an actual "class" attribute. True, `class("a")` returns `"character"`, but if you check `attributes("a")` you get NULL. If you define e.g. `a <- structure("a", class = "character")` and do the same for `b` too, it will work. See https://stat.ethz.ch/pipermail/r-help/2006-May/104751.html and also, this one for how to work around it: https://stackoverflow.com/a/18175871/2416535 – jakub Nov 14 '21 at 10:10
  • @jakub Super! Thanks!!! – chan1142 Nov 14 '21 at 13:17