2012-12-20 9 views
8

Sto cercando i modelli per la manipolazione degli oggetti data.table la cui struttura è simile a quella dei dataframes creati con melt dal pacchetto reshape2. Mi occupo di tabelle di dati con milioni di righe. Le prestazioni sono critiche.Dati dati fuso veloci. Operazioni operabili

La forma generalizzata della domanda è se esiste un modo per eseguire il raggruppamento in base a un sottoinsieme di valori in una colonna e se il risultato dell'operazione di raggruppamento crea una o più nuove colonne.

Una specifica forma di domanda potrebbe essere come utilizzare data.table per realizzare l'equivalente di ciò dcast nella figura seguente:

input <- data.table(
    id=c(1, 1, 1, 2, 2, 2, 3, 3, 3, 3), 
    variable=c('x', 'y', 'y', 'x', 'y', 'y', 'x', 'x', 'y', 'other'), 
    value=c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) 
dcast(input, 
    id ~ variable, sum, 
    subset=.(variable %in% c('x', 'y'))) 

la cui uscita è

id x y 
1 1 1 5 
2 2 4 11 
3 3 15 9 
+0

Sono confuso , mi dispiace - la funzione dcast() funziona senza la coazione di .data.frame(). stai provando a realizzare questo senza usare il pacchetto plyr? –

+0

@AnthonyDamico si, mi piacerebbe farlo senza 'dcast' che è in' reshape2'. Ho rimosso as.data.frame() - grazie per averlo indicato. – Sim

risposta

8

risposta non testati rapida: Sembra che tu stia cercando by-senza-by, aka grouping- by-i:

setkey(input,variable) 
input[c("x","y"),sum(value)] 

Questo è come un veloce avendo in SQL. j viene valutato per ogni riga di i. In altre parole, quanto sopra è lo stesso risultato, ma molto più veloce di:

input[,sum(value),keyby=variable][c("x","y")] 

Quest'ultima sottoinsiemi e evals per tutti i gruppi (dispendiosamente) prima di selezionare solo i gruppi di interesse. Il primo (by-without-by) va direttamente al solo sottoinsieme di gruppi.

I risultati del gruppo verranno restituiti nel formato lungo, come sempre. Ma il rimodellamento su larga scala dei dati aggregati (relativamente piccoli) dovrebbe essere relativamente istantaneo. Questo è il pensiero comunque.

Il primo setkey(input,variable) potrebbe mordere se input ha un sacco di colonne non di interesse. Se è così, forse vale la pena sottoinsiemi le colonne necessarie:

DT = setkey(input[,c("variable","value"),with=FALSE], variable) 
DT[c("x","y"),sum(value)] 

In futuro, quando le chiavi secondarie sono implementate che sarebbe più facile:

set2key(input,variable)    # add a secondary key 
input[c("x","y"),sum(value),key=2] # syntax speculative 

Per gruppo da id così:

setkey(input,variable) 
input[c("x","y"),sum(value),by='variable,id'] 

e incluso id nella chiave potrebbe valere il costo di setkey a seconda dei dati:

setkey(input,variable,id) 
input[c("x","y"),sum(value),by='variable,id'] 

Se si combina un by-without-by con, come sopra, quindi il by-without-by funziona come un sottoinsieme; cioè, j viene eseguito solo per ogni riga di i quando manca (di conseguenza, il nome by-without-by). Quindi è necessario includere variable, di nuovo, nel by come mostrato sopra.

In alternativa, il seguente dovrebbe gruppo dal id sopra l'unione di "x" e "y", invece (ma quanto sopra è quello che hai chiesto per la questione, iiuc):

input[c("x","y"),sum(value),by=id] 
+0

Le chiavi secondarie sarebbero molto utili. In alternativa, un modo per costruire "variazioni" per riferimento usando chiavi diverse. Il pattern che continuo a scoprire è la necessità di cambiare la chiave più volte per le diverse operazioni con la stessa clausola ma diverse clausole di selezione e quindi assemblare manualmente il risultato finale dai datatables di ciascuna operazione. – Sim

3
> setkey(input, "id") 
> input[ , list(sum(value)), by=id] 
    id V1 
1: 1 6 
2: 2 15 
3: 3 34 

> input[ variable %in% c("x", "y"), list(sum(value)), by=id] 
    id V1 
1: 1 6 
2: 2 15 
3: 3 24 

L'ultimo:

> input[ variable %in% c("x", "y"), list(sum(value)), by=list(id, variable)] 
    id variable V1 
1: 1  x 1 
2: 1  y 5 
3: 2  x 4 
4: 2  y 11 
5: 3  x 15 
6: 3  y 9 
+0

Questo esegue 'sum' per tutte le variabili invece di solo' x' e 'y'. Nel mio caso ci sono centinaia di variabili diverse, quindi ho bisogno di una clausola di subsetting. Mi piacerebbe non doverlo fare creando un intero datatable temporaneo. – Sim

+1

questo è più vicino ma ancora non perfetto keycols <- c ("id", "variabile"); setkeyv (input, keycols); input [input $ variabile% in% c ('x', 'y'), lista (somma (valore)), da = keycols] –

+0

@Sim: stavo solo mostrando le opzioni. L'ultimo è tutto ciò di cui hai bisogno e non crea alcuna tabella intermedia. –

2

io non sono sicuro se questo è il modo migliore, ma si può provare:

input[, list(x = sum(value[variable == "x"]), 
      y = sum(value[variable == "y"])), by = "id"] 
# id x y 
# 1: 1 1 5 
# 2: 2 4 11 
# 3: 3 15 9 
+0

Questo non crea due vettori temporanei per l'uguaglianza 'variabile 'per ogni valore di' id'? – Sim

Problemi correlati