编辑:问题略有改变,为什么特定的扩展程序不起作用,而不是为什么一般方法不起作用。
如标题所示,我在将函数扩展到其他(S3)类时遇到了麻烦。
例如:
x <- y <- runif(10)
loessModel = loess(y ~ x)
methods("cor")
## [1] cor.test cor.test.default* cor.test.formula*
cor.loess = function(loessModel, ...) { cor(loessModel$x, loessModel$y, ...) }
cor(loessModel)
## Error in cor(loessModel) : supply both 'x' and 'y' or a matrix-like 'x'
但是,以下工作:
getCor = function(x, y, ...) { UseMethod("getCor") }
getCor.default = function(x, y, ...) { cor(x, y, ...) }
getCor.loess = function(loessModel, ...) getCor(loessModel$x, loessModel$y, ...)
getCor(loessModel)
## [,1]
## x 1
所以...正如Josh所解释的,扩展cor
的第一种方法不起作用,因为cor
不是通用函数。第二种方法有效,但我无法将其扩展为LoessList
类。这对我来说很困惑,特别是因为它在“功能之外”起作用:
set.seed(13)
df = data.frame(id = rep.int(1:2, 10),
x = runif(20),
y = runif(20))
loessList = structure(dlply(df, "id", loess, formula = as.formula("y ~ x")),
class = "LoessList")
getCor.LoessList = function(loessList, ...) { ldply(loessList, getCor, ...) }
getCor(loessList)
## Error in is.data.frame(y) : argument "y" is missing, with no default
ldply(loessList, getCor)
## id 1
## 1 1 -0.01552707
## 2 2 -0.38997723
更一般地说,R中的OOP有什么好的指南吗?我一直使用http://logic.sysbiol.cam.ac.uk/teaching/advancedR/slides.pdf作为我的主要参考点,但其他来源总是受到赞赏。
干杯
答案 0 :(得分:4)
1。 S3中的泛型可以扩展但是如果你想将非泛型变成泛型并扩展它,那么你将需要S4。这里我们定义一个S4泛型,默认为stats::cor
。然后我们将S4方法loess
提供给S4并定义loess
方法:
setGeneric("cor", function(x, ...) stats::cor(x, ...))
setOldClass("loess") # let S4 use an S3 class
setMethod("cor", list(x = "loess"),
def = function(x, ...) callNextMethod(x$x, x$y, ...))
现在我们可以这样做:
example(loess)
cor(cars.lo)
2。如果您想坚持使用S3,另一种方法是使用您自己的S3通用来破解cor
:
cor <- function(x, ...) UseMethod("cor")
cor.default <- stats::cor
cor.loess <- function(x, ...) stats::cor(x$x, x$y, ...)
example(loess)
cor(cars.lo)
3。当然,您可以恰当地重新定义cor
并忘记OO派遣。实际上存在一些潜在的问题,因为它使cor
对执行实际工作的函数的父框架调用,但在许多情况下它并不重要。 (请参阅lm
源代码以了解如何规避此问题。)
cor <- function(x, ...) {
if (inherits(x, "loess")) return(cor(x$x, x$y, ...))
stats::cor(x, ...)
}
信息:有关S3的信息,请参阅该页面上的?UseMethod
以及参考和链接。有关S4的信息,请参阅?Methods
以及该页面上的参考和链接。
更新:添加了其他方法和参考。
答案 1 :(得分:3)
运行methods(cor)
时注意警告。
R> methods("cor")
[1] cor.test cor.test.default* cor.test.formula*
Non-visible functions are asterisked
Warning message:
In methods("cor") : function 'cor' appears not to be generic
cor
不是通用的,因此您不能只定义方法。您也需要定义泛型,这就是您在问题的解决方案中所做的。