25

我无法找出为 S4 类定义 、 和子集运算符[$正确方法。[[

谁能为我提供一个为 S4 类定义这三个的基本示例?

4

2 回答 2

40

发现泛型,以便我们知道我们的目标是什么

> getGeneric("[")
standardGeneric for "[" defined from package "base"

function (x, i, j, ..., drop = TRUE) 
standardGeneric("[", .Primitive("["))
<bytecode: 0x32e25c8>
<environment: 0x32d7a50>
Methods may be defined for arguments: x, i, j, drop
Use  showMethods("[")  for currently available ones.

定义一个简单的类

setClass("A", representation=representation(slt="numeric"))

并实现一个方法

setMethod("[", c("A", "integer", "missing", "ANY"),
    ## we won't support subsetting on j; dispatching on 'drop' doesn't
    ## make sense (to me), so in rebellion we'll quietly ignore it.
    function(x, i, j, ..., drop=TRUE)
{
    ## less clever: update slot, return instance
    ## x@slt = x@slt[i]
    ## x
    ## clever: by default initialize is a copy constructor, too
    initialize(x, slt=x@slt[i])
})

在行动:

> a = new("A", slt=1:5)
> a[3:1]
An object of class "A"
Slot "slt":
[1] 3 2 1

支持(隐式)许多签名有不同的策略,例如,您可能还希望支持逻辑和字符索引值,可能同时支持 i 和 j。最直接的是“门面”模式,其中每个方法对常见类型的子集索引进行一些初步强制,例如,integer允许索引条目的重新排序和重复,然后使用callGeneric调用单个方法子集类的工作。

没有概念上的差异[[,除了要尊重返回内容的语义而不是[. 因为$我们有

> getGeneric("$")
standardGeneric for "$" defined from package "base"

function (x, name) 
standardGeneric("$", .Primitive("$"))
<bytecode: 0x31fce40>
<environment: 0x31f12b8>
Methods may be defined for arguments: x
Use  showMethods("$")  for currently available ones.

setMethod("$", "A",
    function(x, name)
{
    ## 'name' is a character(1)
    slot(x, name)
})

> a$slt
[1] 1 2 3 4 5
于 2012-06-09T14:55:26.873 回答
9

我会按照@Martin_Morgan 为您提到的运营商建议的那样做。不过我要补充几点:

1)我会小心定义一个$运算符来访问 S4 插槽(除非您打算从存储在特定插槽中的数据帧中访问列?)。一般建议是编写访问器函数getMySlot(),并setMySlot()获取您需要的信息。您可以使用@运算符从这些插槽访问数据,尽管 get 和 set 最好用作用户界面。使用$可能会让用户感到困惑,他们可能会期望 data.frame。有关这些问题的深入讨论,请参阅Christophe Genolini 的此S4 教程。如果这不是您打算使用的方式$,请忽略我的建议(但本教程仍然是一个很好的资源!)。

2) 如果您要定义[[[从另一个类继承,例如vector,您还需要定义el()(等价于[][[1L]],或子集的第一个元素[])和length()。我目前正在编写一个从数字继承的类,数字方法将自动尝试从您的类中使用这些函数。如果课程是为了更有限的或您自己的个人用途,这可能不是问题。

抱歉,我会将此作为评论留下,但我是 SO 新手,我还没有代表!

于 2012-07-03T15:14:25.027 回答