2013-08-04 5 views
11
> library(data.table) 
> A <- data.table(x = c(1,1,2,2), y = c(1,2,1,2), v = c(0.1,0.2,0.3,0.4)) 
> A 
    x y v 
1: 1 1 0.1 
2: 1 2 0.2 
3: 2 1 0.3 
4: 2 2 0.4 
> B <- dcast(A, x~y) 
Using v as value column: use value.var to override. 
> B 
    x 1 2 
1 1 0.1 0.2 
2 2 0.3 0.4 

A quanto pare riesco a rimodellare un data.table da lungo a largo usando f.x. dcast di pacchetto reshape2. Ma data.table arriva insieme ad un operatore di staffe sovraccarico che offre parametri come 'by' e 'group', che mi chiedo se è possibile raggiungerlo usando questa (per funzionalità specifiche di data.table)?Rimodellare data.table strutturata lunga in una struttura ampia utilizzando la funzionalità data.table?

Solo un esempio a caso da manuale:

DT[,lapply(.SD,sum),by=x] 

che sembra impressionante - ma non capisco pienamente l'utilizzo ancora.

Non ho trovato né un modo né un esempio per questo, quindi forse non è possibile, forse non è nemmeno previsto che sia - quindi, un preciso "no, non è possibile perché ..." è ovviamente anche una risposta valida.

+0

Vedere [qui] (http://stackoverflow.com/questions/15510566/nested-if-else-statements-over-a-number-of-columns/15511689?noredirect=1#comment21968080_15511689). – Metrics

+0

Siamo spiacenti, non vedo come questo si riferisce alla mia domanda. Si noti inoltre che le categorie di colonne di B sono dinamicamente dipendenti da A, quindi il numero di valori di "y" può variare da caso a caso. – Raffael

risposta

15

Prenderò un esempio con gruppi diseguali in modo che sia più facile da illustrare per il caso generale:

A <- data.table(x=c(1,1,1,2,2), y=c(1,2,3,1,2), v=(1:5)/5) 
> A 
    x y v 
1: 1 1 0.2 
2: 1 2 0.4 
3: 1 3 0.6 
4: 2 1 0.8 
5: 2 2 1.0 

Il primo passo è per ottenere il numero di elementi/voci per ciascun gruppo di "x" uguale. Qui, per x = 1 ci sono 3 valori di y, ma solo 2 per x = 2. Quindi, dovremo risolverlo prima con NA per x = 2, y = 3.

setkey(A, x, y) 
A[CJ(unique(x), unique(y))] 

Ora, per farlo di grande formato, dovremmo gruppo da "x" e utilizzare as.list su v come segue:

out <- A[CJ(unique(x), unique(y))][, as.list(v), by=x] 
    x V1 V2 V3 
1: 1 0.2 0.4 0.6 
2: 2 0.8 1.0 NA 

Ora, è possibile impostare i nomi delle colonne continuamente modificato l'utilizzo di riferimento con setnames come segue:

setnames(out, c("x", as.character(unique(A$y))) 

    x 1 2 3 
1: 1 0.2 0.4 0.6 
2: 2 0.8 1.0 NA 
+0

In realtà la tua prima soluzione non è indicata nel tuo post. Quindi lo terrò per ragioni accademiche! Grazie mille per lo sforzo! – Raffael

+0

La prima soluzione funziona quando ci sono già file uguali per ogni gruppo. Ed è meglio impostare i nomi delle colonne una volta alla fine piuttosto che impostarle per ogni gruppo (che è ciò che fa la vecchia soluzione). Potrebbero esserci problemi di prestazioni dovuti a dati più grandi. – Arun

+1

Ok, questa soluzione l'avrei trovata dopo aver studiato il manuale per settimane, immagino ... quindi, questo potrebbe essere molto soggettivo, ma penso di poter dire con certezza che questa soluzione è piuttosto complessa ed elaborata - non c'è dubbio però a riguardo è la soluzione più semplice possibile usando semplicemente data.table come ho chiesto. Quindi, vorrei sapere da voi se forse quest'area di rimodellamento dei dataset non è solo ciò che data.table dovrebbe effettivamente affrontare. Dove tracciare la linea per quanto riguarda un uso economico e ragionevole dei dati.table e dove ricorrere a ulteriori strumenti? – Raffael

2

(con crediti a Arun)

A[, setattr(as.list(v), 'names', y), by=x] 
+0

abbiamo un affare qui! – Raffael

+0

Errore in '[.data.table' (A,, setattr (as.list (v)," nomi ", y), per = x): j non valuta lo stesso numero di colonne per ogni gruppo – skan

10

Usa dcast() (ora un metodo predefinito data.table, a partire dalla versione 1.9 .5; le versioni precedenti utilizzano dcast.data.table) come in

> dcast(A,x~y) 
Using 'v' as value column. Use 'value.var' to override 
    x 1 2 3 
1: 1 0.2 0.4 0.6 
2: 2 0.8 1.0 NA 

Questo è veloce e evita la necessità di setnames().

È anche particolarmente utile quando nell'esempio precedente è una variabile fattore con livelli di carattere - ad es. 'Basso', 'Medio', 'Alto' - perché CJ() potrebbe non restituire i dati di larghezza con le variabili nell'ordine che si aspetta setnames() e si può finire male con i dati erroneamente erroneamente etichettati.

+0

+1. Grazie per aver aggiornato questa risposta con 'dcast.data.table'. – Arun