Как написать функцию ac () для пользовательского класса S3 в R - PullRequest
6 голосов
/ 22 ноября 2010

Я пишу класс S3 в R, который представляет собой целое число с некоторыми прикрепленными к нему атрибутами.Если 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

Здесь результатом является просто вектор элементов числового класса, а исходный атрибут nушел.

Глядя на код для различных пакетов, я иногда вижу код, подобный следующему, в котором нам нужно сохранить атрибут класса, но ничего больше:

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

К сожалению, я также не могузаставить это работать.Результатом вызова c.myclass (x1, x2) является вектор, в котором сам вектор имеет класс «myclass», но где каждый элемент в векторе имеет класс numeric;Я действительно хочу, чтобы у каждого элемента в векторе был класс "myclass".На практике мне также потребуется обновить этот метод, чтобы сохранить и другие атрибуты (например, атрибут "n" в myclass).

Ответы [ 2 ]

7 голосов
/ 22 ноября 2010

Вот пример, который делает (я думаю) то, что вы хотите с помощью специальных методов для 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.

. Может быть более естественным работать с универсальным вектором, списком.Бит, который является более сложным, и, возможно, вышеупомянутого достаточно в вашем случае?

4 голосов
/ 22 ноября 2010

Это работает, но я предполагаю, что вы пришли к выводу, что каждый элемент вектора имеет числовой класс, потому что вы делаете что-то вроде этого:

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

Если это так, и вы хотите, чтобы извлеченные элементы сохраняли myclass атрибут, вам нужно написать метод подмножества "[.myclass", чтобы сохранить атрибуты.

...