Skip to content

Missing generic + method #3986

Open
Open
@schloerke

Description

@schloerke

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions