ggplot2
ggplot2 copied to clipboard
Missing generic `+` method
(cc @clauswilke https://github.com/tidyverse/ggplot2/pull/3818#issuecomment-623055651)
Context
Let's say foo is a class defined by a package other than ggplot2 (Ex: patchwork or GGally). foo objects also inherit from gg. bar objects do not inherit from gg
You can currently perform gg_obj + foo_obj as both objects inherit from gg and would produce the same +.gg method from Opt's double dispatch.
Currently, to control how the right-hand-side (foo objects) are added, we can define ggplot_add.foo.
Problem
However, currently we can not customize how left-hand-side objects (ex: foo_obj + gg_obj) are added to gg objects.
Ex: left hand side structures are not ggplot2 objects and will not work with ggplot2 internal methods
x <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
foo_obj <- structure(
list(x, x),
class = c("foo", "gg")
)
# can not customize how the theme is added
foo_obj + theme_bw()
Ex: conflicting + methods make addition impossible
x <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
bar_obj <- structure(
list(x, x),
class = c("bar") # does not inherit from 'gg'
)
`+.bar` <- function(e1, e2) {
# only add to second plot
e1[[2]] <- e1[[2]] + e2
e1
}
# Conflicting `+` methods
bar_obj + theme_bw()
#> Error in bar_obj + theme_bw() : non-numeric argument to binary operator
#> In addition: Warning message:
#> Incompatible methods ("+.bar", "+.gg") for "+"
Real life situation
-
To get around this in
GGally, I overwrite the+.ggmethod. Unfortunately, this produces a warning and does not dispatch to the next available plus method. I am open to other options, but I don't know how to produce one that would play well with other packages. -
I would like to be able to add a scale to a
ggmatrixobject in appropriate places only (Ex:ggmatrix_obj + gg_scale_obj). With the current methods, I don't know how I can do this cleanly.
Goal
Define a generic add method (ex: add_gg(e1, e2)). This generic add method should be called within +.gg to avoid double dispatch confusion involving +.
ggplot2's +.gg is not commutative. So I believe this situation has merit.
Using the implementation in https://github.com/tidyverse/ggplot2/pull/3818 , I would be able to define how a theme object is added to a custom object.
library(ggplot2)
x <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
foo_obj <- structure(
list(x, x),
class = c("foo", "gg")
)
`add_gg.foo` <- function(e1, e2) {
# only add to second plot
e1[[2]] <- e1[[2]] + e2
e1
}
print.foo <- function(x, ...) {
gridExtra::grid.arrange(x[[1]], x[[2]], ncol = 2)
}
foo_obj + theme_bw()

Created on 2020-02-11 by the reprex package (v0.3.0)
I would also appreciate seeing this added to ggplot2 as it will give me a way to insure my new class object is still valid after vanilla ggplot2 layers are added. Currently, I either have to override +.gg or write a ggplot_build method to insure my object is still valid.