在Perl(可能还有其他语言)中,您可以"绑定"变量以使用用户定义的行为替换它的内置行为.例如,哈希表可以与自定义"get"和"fetch"子例程绑定,例如,查询BerkeleyDB以使数据持久且不受RAM限制,但仍然看起来像Perl的常规哈希.
与R有类似的可能吗?特别是,我在思考,因为它data.frame
看起来很像关系数据库中的一个表,如果data.frame
它与SQLite这样的东西联系在一起,它会使R能够处理非常大的数据帧(我已经把100GB +填入了SQLite)而没有代码更改.
正如评论所指出的,一些软件包已经基于这个想法(或类似的想法)构建。
data.table
并且dplyr
非常擅长处理非常大的 data.frame 并查询它们。如果 data.frame 实际上 >100GB,我宁愿推荐 data.table,它在限制 nrow->Inf 中似乎优于 dplyr。如果您需要的话,两者在 stackoverflow 上都有出色的支持。
然而,要真正回答你的问题(并且对这个问题的未来读者有用):是的,可以用 R 附加函数来提供替代行为。使用S3调度系统实际上非常容易。我推荐此资源以了解更多信息。
我会给你一个精简版本:如果你有一个“myclass”类的对象,你可以编写一个函数 f.myclass 来执行你想要的操作。
然后定义通用函数 f:
f <- function(obj, ...) UseMethod("f", obj, ...)
Run Code Online (Sandbox Code Playgroud)
当您调用 时f(obj)
,将调用的函数UseMethod
取决于 obj 的类。
如果 obj 属于“myclass”类,则将在 obj 上调用 f.myclass。
如果您要重新定义的函数已经存在,例如plot
,那么您可以简单地定义在调用“myclass”对象plot.myclass
时将使用哪个函数。plot
通用函数已经存在,无需重新定义。
要更改对象的类(或将新类附加到现有类,这更常见,不会破坏您不想更改的行为),您可以使用class<-
.
这是一个愚蠢的例子。
> print.myclass <- function(x) {
print("Hello!")}
> df <- data.frame(a=1:3)
> class(df)
[1] "data.frame"
> df #equivalent to print(df)
a
1 1
2 2
3 3
> class(df) <- append(class(df), "myclass")
> class(df)
[1] "data.frame" "myclass"
> class(df) <- "myclass"
> class(df)
[1] "myclass"
> df
[1] "Hello!"
> str(df) # checking the structure of df: the data is still there of course
List of 1
$ a: int [1:3] 1 2 3
- attr(*, "row.names")= int [1:3] 1 2 3
- attr(*, "class")= chr "myclass"
Run Code Online (Sandbox Code Playgroud)
有一些微妙之处,例如如果有多个类,则调用哪个函数,按什么顺序调用等。我建议您参阅 S3 系统的全面解释。
这就是重新定义函数行为的方式。将它们重写为f.myclass
,然后创建类“myclass”的对象。
或者,您可以重新定义 f.targetclass。例如,再次使用print
and data.frame
:
> print.data.frame <- function(x) {
print(paste("data.frame with columns:", paste(names(x), collapse = ", ")))} # less silly example!
> df <- data.frame(a=1:3, b=4:6)
> df
[1] "data.frame with columns: a, b"
Run Code Online (Sandbox Code Playgroud)