2010-11-22 10 views
6

J'écris une classe S3 dans R qui est juste un entier avec des attributs attachés. Si x1 et x2 sont des objets de cette classe (appelez-la "myclass"), alors je voudrais que c (x1, x2) renvoie un vecteur d'objets myclass avec la définition de classe d'origine et les attributs intacts. Cependant, le comportement documenté de c() est de supprimer des attributs, il semblerait donc que j'ai besoin d'écrire ma propre méthode c.myclass(). Ma question est, comment puis-je faire cela?Comment écrire une fonction c() pour une classe S3 personnalisée dans R

Un exemple du problème:

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

Voici le résultat est juste un vecteur d'éléments de classe numériques, et l'attribut original n est parti.

En regardant le code pour différents forfaits, je vois parfois code comme suit, dans laquelle nous devons conserver l'attribut de classe mais rien d'autre:

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

Malheureusement je ne peux pas non plus que cela fonctionne. Le résultat de l'appel de c.myclass (x1, x2) est un vecteur où le vecteur a lui-même la classe "myclass" mais où chaque élément du vecteur a une classe numérique; Je veux vraiment que chaque élément du vecteur ait la classe "myclass". En pratique, je devrai également mettre à jour cette méthode pour préserver d'autres attributs (comme l'attribut "n" dans myclass).

Répondre

4

Cela fonctionne, mais je suppose que vous en conclure que chaque élément de vecteur a numérique de classe parce que vous faites quelque chose comme ceci:

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

Si tel est le cas et que vous souhaitez des éléments extraits de conserver l'attribut myclass , vous devez écrire une méthode de sous-ensemble "[.myclass" pour conserver les attributs.

+0

Merci Joshua, votre suggestion a fonctionné. – Abiel

7

Voici un exemple qui fait (je pense) ce que vous voulez via des méthodes spécifiques pour c et [:

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] 

Mais c'est un fudge dans que nous devons gérer la manipulation du réglage et subsetting extra attributs pour contenir le n. Ceci est vraiment juste un vecteur numérique avec un attribut pour l'enregistrement n.

Il peut être plus naturel de travailler avec le générique de tous les vecteurs, une liste. Bit qui est plus impliqué et peut-être ce qui précède est suffisant dans votre cas?