我正在实现一个包含 data.table 的 S4 类,并尝试实现对象的 [ 子集(如 here 所述),以便它也子集 data.table 。例如(仅定义 i 子集):

library(data.table)

.SuperDataTable <- setClass("SuperDataTable", representation(dt="data.table"))

setMethod("[", c("SuperDataTable", "ANY", "missing", "ANY"),
    function(x, i, j, ..., drop=TRUE)
{
    initialize(x, dt=x@dt[i])
})

d = data.table(a=1:4, b=rep(c("x", "y"), each=2))
s = new("SuperDataTable", dt=d)

此时,使用数字向量 ( s[1:2] ) 进行子集化可按预期工作(它对槽中的 data.table 进行子集化)。但是,我想添加使用表达式进行子集化的功能。这适用于 data.table 本身:
s@dt[b == "x"]
#    a b
# 1: 1 x
# 2: 2 x

但不适用于 S4 [ 方法:
s[b == "x"]
# Error: object 'b' not found

问题似乎是 S4 方法签名中的参数没有使用 R 的传统惰性求值进行求值 - 请参阅 here :



这解释了为什么它不起作用,但不能解释如何实现这种子集,因为 ij 包含在泛型的签名中。有没有办法不立即评估 i 参数?

最佳答案

你可能在这方面不走运。从 R developer notes



此外,由于方法缓存,



我将遵循 data.table 包编写者的示例并使用 S3 对象(请参阅 source codeR/data.table.R 的第 304 行)。您的 S3 对象仍然可以在下面创建和操作 S4 对象以保持半静态键入功能。

我们不能变得特别聪明:

 ‘[’ is a primitive function;  methods can be defined, but the generic function is implicit, and cannot be changed.

同时定义 S3 和 S4 方法将调度 S3 方法,这使得我们看起来应该能够绕过 S4 调用并手动调度它,但不幸的是参数评估仍然发生!您可以通过借用 plyr::. 来接近,这将为您提供如下语法:
s <- new('SuperDataTable', dt = as.data.table(iris))
s[.(Sepal.Length > 4), 2]

不理想,但比其他任何东西都更接近。

关于r - S4 方法参数的惰性求值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22593102/

10-12 14:01