R:修改应用于S4类的任何函数

时间:2016-09-23 13:40:32

标签: r methods closures s4

我一直在开发一个S4类,它本质上是一个带有一点额外信息的data.frame。出于这个问题的目的,这个类的“额外”特征是无关紧要的。重要的是该类包含一个存储在其中一个插槽中的data.frame对象。 (我将data.frame放在一个插槽中,而不是将其命名为超类,因为我发现包含data.frames的S4类由于某种原因将data.frames简化为列表。)

这是一个基本的例子:

setClass('tmp_class', slots = c(df = 'data.frame'))

test_object <- new('tmp_class', df = data.frame(Num = 1:10, Let = letters[1:10]))

现在我想要做的是使应用于此类对象的任何函数应用于插槽@df中的data.frame。编写特定函数的方法很容易,例如:

setMethod('dim', signature = c(x = 'tmp_class'), function(x) dim(x@df))

但我只限于我能想到的功能,而且用户发明的任何功能都不起作用。

编写一种包装器/闭包来修改一个函数来处理我的类是一件很简单的事情,如下所示:

tmp_classize <- function(func){
   function(tmp, ...){ func(tmp@df, ...) }
}

所以,不是为colnames()或ncol()编写方法,而是运行:

tmp_classize(colnames)(test_object)

tmp_classize(ncol)(test_object)

但我想做的是以某种方式在我自己的任何函数上唤起我的“tmp_classize”函数。我无法弄清楚该怎么做。我想如果可以某种方式调用带有“tmp_class”类的输入签名的“通用方法”,然后使用sys.function()来获取被调用的实际函数,也许我可以使某些东西工作,但是A)那里是递归问题B)我不知道如何称这种“通用”方法。在我看来,解决方案,如果它存在,可能需要非标准的评估,我宁愿避免,但可能会在必要时使用。

谢谢!

P.S。我意识到这项任务可能是不明智/糟糕的编程技术,我可能永远不会在包中实现它。我仍然很想知道是否有可能。

P.P.S。我也对应用于S3类的相同想法感兴趣!

2 个答案:

答案 0 :(得分:0)

原则上,您可以为您的班级和classUnion创建一个data.frame,并为您的班级编写处理所有读写data.frames的方法的方法。如$[dim()<-等等。然后,当其他函数试图将您的新类用作data.frame时,将有一些方法可以使用它。这在John Chambers&#34; Software for Data Analysis&#34;从第375页开始。那说这个系统可能很难实现。

更简单的系统可能只是为您的data.frame添加额外的属性,并提供您需要的额外信息。例如:

x<-data.frame(a=1:3,b=4:6)
attr(x,"Info")<-"Extra info I need"
attributes(x)$Info
[1] "Extra info I need"

这不像S4类那样优雅,但会执行data.frame所做的所有事情。我怀疑那些熟悉S3课程的人可以改进这个想法。

答案 1 :(得分:0)

最简单的解决方案是让您的班级包含 data.frame,而不是将其作为其中一个广告位。例如,这里是带有时间戳的data.frame

setclass(
  "timestampedDF",
  slots=c(timestamp="POSIXt"),
  contains="data.frame"
)

现在,适用于data.frame的所有功能(例如head)将自动适用于timestampedDF个对象。如果您需要访问&#34;数据框部分&#34;,那么它将保存在隐藏的广告位object@.Data中。