2013-02-07 9 views
9

Ho provato ad associare la mia classe a numeric, per modificare l'output format. Funziona bene, ma dopo che faccio un gruppo by la classe ritorna al valore numerico.Perché data.table perde la definizione della classe in .SD dopo il gruppo per?

Esempio: Definire una nuova funzione di formattazione per la mia classe:

format.myclass <- function(x, ...){ 
    paste("!!", x, "!!", sep = "") 
} 

poi fare una piccola data.table e cambiare una delle colonne per MyClass:

> DT <- data.table(L = rep(letters[1:3],3), N = 1:9) 
> setattr(DT$N, "class", "myclass") 
> DT 
    L  N 
1: a !!1!! 
2: b !!2!! 
3: c !!3!! 
4: a !!4!! 
5: b !!5!! 
6: c !!6!! 
7: a !!7!! 
8: b !!8!! 
9: c !!9!! 

Ora eseguire un gruppo e la colonna N ritorna a intero:

> DT[, .SD, by = L] 
    L N 
1: a 1 
2: a 4 
3: a 7 
4: b 2 
5: b 5 
6: b 8 
7: c 3 
8: c 6 
9: c 9 

> DT[, sapply(.SD, class), by = L] 
    L  V1 
1: a integer 
2: b integer 
3: c integer 

Qualche idea del perché?

risposta

8

Perché ogni volta che R riceve un vettore, getta via la classe. Perché? Bene, perché è un asino, ecco perché. Devi scrivere un metodo "[" -subset.

> DT[,N] 
[1] 1 2 3 4 5 6 7 8 9 
attr(,"class") 
[1] "myclass" 
> DT[1:2,N] 
[1] 1 2 

vedere in che modo il vettore ha rimosso la classe? Questo è il problema. data.table sta facendo questo a un certo punto del tuo vettore. Scrivi un metodo "[" (copia solo quello utilizzato da Data):

"[.myclass"= function (x, ..., drop = TRUE){ 
    cl <- oldClass(x) 
    class(x) <- NULL 
    val <- NextMethod("[") 
    class(val) <- cl 
    val 
} 

> DT[1:2,N] 
[1] 1 2 
attr(,"class") 
[1] "myclass" 

e ora ha qualche classe. Questo risolve anche la tua ultima linea con il sapply:

> DT[, sapply(.SD, class), by = L] 
    L  V1 
1: a myclass 
2: b myclass 
+2

+1 per "culo". E un'ottima risposta – Corone

+3

+1. Avrei giurato '.SD' attributi di colonne mantenute ma chiaramente no. Lo risolverà, a meno che non ci sia un rovescio della medaglia? (So ​​che non ci sarà alcun aspetto negativo delle prestazioni, quindi intendo diversamente). –

+2

Non so davvero perché questo non è il comportamento predefinito. Oppure quante copie di "[.Date" si trovano su CRAN con diversi alias. La vera soluzione sarebbe quella di sottoclasse da "Date" e ottenere gratuitamente quella funzione di sottoinsieme :) j/k – Spacedman

Problemi correlati