使用sd作为R中的通用函数

时间:2011-01-18 19:48:20

标签: oop r r-s3

如果我有一个名为foo的类,则可以直接重载summary函数

summary.foo = function(x, ...) print("bar")

然而,这种技术不适用于sd函数,即

> bar = createFooClass()
> sd.foo = function(x, ...) print("Hi")
> sd(bar)
  error: is.atomic(x) is not TRUE

重载此功能的正确方法是什么?

3 个答案:

答案 0 :(得分:7)

您可以劫持任何非泛型函数,使其(S3)泛型并将原始版本设置为默认版本。例如:

## make an S3 generic for sd
sd <- function(x, ...) UseMethod("sd")
## take the usual definition of sd,
## and set it to be the default method
sd.default <- stats::sd
## create a method for our class "foo"
sd.foo = function(x, ...) print("Hi")

最后一步,如果它在一个包中,就是向...添加一个sd.default参数,以允许传递包检查:

formals(sd.default) <- c(formals(sd.default), alist(... = ))

,并提供:

> args(sd.default)
function (x, na.rm = FALSE, ...) 
NULL
> args(stats::sd)
function (x, na.rm = FALSE) 
NULL

然后给出了所需的行为:

> bar <- 1:10
> sd(bar)
[1] 3.027650
> class(bar) <- "foo"
> sd(bar)
[1] "Hi"

这在写作R扩展手册的section 7.1中有记录

答案 1 :(得分:3)

您需要为sd定义新的通用。

最简单的方法是使用S4,因为它会自动处理默认的“sd”方法:

setClass("foo", list(a = "numeric", names = "character"))

setGeneric("sd")

setMethod("sd", "foo", 
          function(x,  na.rm = FALSE){
              print("This is a foo object!")
              callNextMethod(x@a)
              })

tf <- new("foo", a = 1:10)
sd(tf)
#[1] "This is a foo object!"
#[1] 3.027650

答案 2 :(得分:1)

查看sd()的代码---它有效地在内部发送。换句话说,它不是通用函数,而是普通的常规函数​​。

最简单的可能就是修改sd()以在类foo上进行分支。