Skip to content

Missing generic + method #3986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
schloerke opened this issue May 5, 2020 · 1 comment · May be fixed by #5537
Open

Missing generic + method #3986

schloerke opened this issue May 5, 2020 · 1 comment · May be fixed by #5537
Labels
feature a feature request or enhancement internals 🔎

Comments

@schloerke
Copy link
Contributor

(cc @clauswilke #3818 (comment))

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 +.gg method. 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 ggmatrix object 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 #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)

@thomasp85 thomasp85 added the feature a feature request or enhancement label Aug 31, 2020
@jtlandis
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement internals 🔎
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants