为 `+` 定义 data.frame 方法并在 ggplot 对象上使用时二元运算符的非数字参数

non-numeric argument to binary operator when defining a data.frame method for `+` and using on ggplot object

我可以这样定义 S3 方法:

`+.data.frame` <- function(e1,e2){"hello"}
iris + iris
# [1] "hello"

但是如果 e2 是一个 gg 对象,这将不起作用:

iris + geom_point()

Error in iris + geom_point() : non-numeric argument to binary operator

In addition: Warning message: Incompatible methods ("+.data.frame", "+.gg") for "+"

我认为这与 S4 方法有关,但我很困惑。你能解释一下发生了什么以及如何解决它吗?

期望的输出:

iris + geom_point()
# [1] "hello"

这其实不是S4方法的问题,而是方法冲突。 geom_point() 和您的数据框都不是 S4 对象(isS4 returns FALSE),因此 S4 方法不会起作用。

ggplot包在gg-classed对象上为+定义了一个方法,而你刚刚为data.frames定义了一个方法.问题是,与大多数 S3 通用函数不同,+ 在选择方法时会考虑 参数中的 class。在这种情况下,它得出结论,它可以合法地选择 gg 方法以及 data.table 方法。

来自 "Ops"(其中“+”是成员)的帮助页面:

The classes of both arguments are considered in dispatching any member of this group. For each argument its vector of classes is examined to see if there is a matching specific (preferred) or Ops method. If a method is found for just one argument or the same method is found for both, it is used. If different methods are found, there is a warning about ‘incompatible methods’: in that case or if no method is found for either argument the internal method is used.

所以你看到在这种情况下,它落入了默认的 + 代码,它不知道如何添加数据帧和 gg 对象,并且 returns说错了。

为了解决这个问题,您可以编写一个带有签名 (data.frame,gg) 的 S4 方法(或者可能 (data.frame,ANY) 但要注意——只有当其中一个参数是S4 对象(默认情况下 data.frames 不是)。您可能必须定义自己的 class,其中包含 data.frame(或者,包含 gg)以触发方法。