我一直在开发一个 S4 类,它本质上是一个带有一些额外信息的 data.frame。就此问题而言,此类的“额外”功能无关紧要。重要的是该类包含一个存储在其中一个槽中的 data.frame 对象。 (我将 data.frame 放在一个插槽中,而不是将其命名为父类(super class),因为我发现包含 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) 我不知道如何调用这样的“通用”方法。在我看来,解决方案(如果存在的话)可能需要进行非标准评估,我宁愿避免这种情况,但在必要时可能会使用。
谢谢!
附言我意识到这项工作可能是不明智的/糟糕的编程技术,而且我可能永远不会在包中实际实现它。我仍然很好奇这是否可能。
附言我也对应用于 S3 类(class)的相同想法感兴趣!
最佳答案
原则上你可以做一个 classUnion
为你的类(class)和data.frame
并为您的类编写处理所有读写方式的方法 data.frames
例如$
, [
, dim()
, <-
还有很多。然后当其他函数试图将您的新类用作 data.frame
时将有一些方法可以使它起作用。这在 John Chambers 从第 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
类可以在这个想法上改进很多。
关于R:修改应用于 S4 类的任何函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39662297/