如何在R中为自定义S3类编写c()函数

时间:2010-11-22 00:13:38

标签: r r-s3

我在R中编写一个S3类,它只是一个附加了一些属性的整数。如果x1和x2是这个类的对象(称之为“myclass”),那么我希望c(x1,x2)返回myclass对象的向量,原始类定义和属性保持不变。但是,c()的记录行为是删除属性,所以我似乎需要编写自己的c.myclass()方法。我的问题是,我该怎么做?

问题的一个例子:

myclass <- function(x, n) structure(x, class="myclass", n=n)
x1 <- myclass(1, 5)
x2 <- myclass(2, 6)
c(x1, x2)
[1] 1 2

这里的结果只是类numeric的项向量,原来的n属性消失了。

查看各种包的代码,我有时会看到如下代码,其中我们需要保留class属性,而不是其他:

c.myclass <- function(..., recursive = F) {
    structure(c(unlist(lapply(list(...), unclass))), class="myclass")
}

不幸的是,我也无法让这个工作。调用c.myclass(x1,x2)的结果是一个向量,其中向量本身具有类“myclass”,但是向量中的每个项都有类numeric;我真的希望向量中的每个项都有类“myclass”。在实践中,我还需要升级此方法以保留其他属性(例如myclass中的属性“n”)。

2 个答案:

答案 0 :(得分:7)

以下是通过c[的具体方法(我认为)所需的示例:

c.myclass <- function(..., recursive = FALSE) {
    dots <- list(...)
    ns <- sapply(dots, attr, which = "n")
    classes <- rep("myclass", length(dots))
    res <- structure(unlist(dots, recursive = FALSE), class = classes)
    attr(res, "n") <- ns
    res
}

`[.myclass` <- function (x, i) {
    y <- unclass(x)[i]
    ns <- attr(x, "n")[i]
    class(y) <- "myclass"
    attr(y, "n") <- ns
    y
}


myclass <- function(x, n) structure(x, class = "myclass", n = n)
x1 <- myclass(1, 5)
x2 <- myclass(2, 6)
c(x1, x2)
c(x1, x2)[2]

但这是一种软糖,因为我们必须管理处理额外属性的设置和子集以保存n。这实际上只是一个带有用于记录n的属性的数字向量。

使用所有向量的通用列表可能更自然。在你的情况下,更多涉及的位可能就足够了吗?

答案 1 :(得分:4)

这确实有效,但我假设你得出结论,每个向量元素都有类数字,因为你做的是这样的:

foo <- c(x1, x2)
class(foo[1])
class(foo[2])

如果是这种情况,并且您希望提取的元素保留myclass属性,则需要编写子集方法"[.myclass"以保留属性。