如何创建具有附加功能的data.frame子类

时间:2013-05-05 18:52:03

标签: r s4

我想创建一个几乎是数据框的类,有一些增强功能(额外的功能,额外的属性),我想知道最好的方法是什么。该类基本上是一个数据框,但有一些额外的属性,例如该数据框的模式(下面命名为“form”,自动派生,表示为数据框,用于将数据框转换为正确的类型),还有其他几件事。当用户在其他不识别其特殊类型的函数中使用此对象时,我希望它们处理对象的data.frame部分。这样做的最佳方式是什么?

我发现的两种方法都不令人满意;我列出了他们以及我仍然看到并试图解决的问题;问题是:做我想做的最好的方法是什么?

方法1,使用“data.frame”作为“基础”插槽 (inspired by this SO post)

setClass("formhubData", representation(form="data.frame"), contains="data.frame")
fd <- new('formhubData', data.frame(x=c(1,2)), form=data.frame(name='x', type='select one', label='X'))

这种方法允许我做以下事情:

fd$x                  >> 1 2
names(fd)             >> "x"

[更新:结果“分解”是由我的环境造成的,我用不同的参数反复调用setClass('formhubData',...)。在新的R会话中,以下所有功能都按预期工作。]

但它很快崩溃了:

nrow(fd)              >> NULL
colnames(fd)          >> NULL

与上面链接的帖子不同,即使简单的is.data.frame也不适用于我

is.data.frame         >> FALSE

方法2,使用“数据”插槽(受SP启发)

setClass("formhubData", representation(data="data.frame", form="data.frame"))
fd <- new('formhubData', data=data.frame(x=c(1,2)), form=data.frame(name='x', type='select one', label='X'))

我丢失了默认定义:

fd$x             >> NULL
names(fd)        >> integer(0)

但是,至少我可以重新定义它们中的大部分(仍然需要了解[,[[,等等]:

 dim.formhubData <- function(x) dim(x@data)
 names.formhubData <- function(x) names(x@data)
 nrow(fd)        >> 2
 names(fd)       >> "x"

然而,似乎我无法表达这样一个事实:对于任何采用data.frame的方法,我的类应该被用作其@data插槽的直通。我觉得需要*.formhubData <- function(x, ...) *(x, ...)这样的东西,而不是试图猜测我班级客户可能使用的所有功能,并将它们定义为dim.formhubDatanames.formhubData等。

有没有办法实现这样的目标?

1 个答案:

答案 0 :(得分:1)

虽然这两种方法在某种程度上都有效,但我实际上建议使用方法2.“标准”面向对象的关于'is-a'与'has-a'设计的考虑因素通常不利于'has-a' 。此外,在R中,方法可以随时添加到对象中,因此在某些方面,“is-a”是一种广告,它可以为您的班级做任意数量的任意事物。即使对于子设置这样的已定义函数,这也是一个难以实现的合同 - 大概是如果用户将行或列添加/添加到data中的基础formhubData,您想要更新form中的信息。

相反,您似乎真的想实现'has-a'关系,并利用这个机会将界面限制为有意义的操作。通过对底层实现的简单调度,您仍然可以通过最少的新代码重复使用大量代码,例如,

setMethod(dim, "formhubData", function(x) dim(x@data)
例如,

会为您提供nrowncol。对于常见操作(例如,子集化),您希望提供尊重数据结构完整性的实现。如果真的是用户应该能够做几乎任意的事情,你可以为data提供简单的“访问者”,也许使用setter来执行{{1}所需的任何操作。 }字段与用户提供的更新的data.frame一致。