2015-04-28 4 views
6

Quando si uniscono data.tables X e Y utilizzando X [Y], X deve avere un tasto, che viene utilizzato dalla chiave di Y per effettuare il join. Se X è una tabella molto grande e normalmente viene digitata su colonne non utilizzate nel join, la chiave di X deve essere modificata per il join e quindi ripristinata sulla chiave originale dopo il join. C'è un modo efficace per fare il join, senza perdere la chiave principale originale su X?Come eseguire un join di data.table X [Y], senza perdere una chiave principale esistente su X?

Ho un dataset ambientale serie DT di grandi dimensioni (1M righe, 36 colonne), come data.table con chiave nelle colonne sito e data. Ho bisogno di fare calcoli su colonne esistenti in DT e/o inserire una nuova colonna, basata su una colonna esistente, usando una piccola ricerca o tabella di ricodifica.

Ecco un esempio minimo:

require(data.table) # using v1.9.5 

# main data table DT, keyed on site and date, with data column x 
DT <- data.table(site = rep(LETTERS[1:2], each=3), 
       date = rep(1:3, times=2), 
       x = rep(1:3*10, times=2), 
       key = "site,date") 
DT 
# site date x 
# 1: A 1 10 
# 2: A 2 20 
# 3: A 3 30 
# 4: B 1 10 
# 5: B 2 20 
# 6: B 3 30 

# lookup table for x to y lookup, keyed on x 
x2y <- data.table(x = c(10,20), y = c(100,200), key = "x") 
x2y 
#  x y 
# 1: 10 100 
# 2: 20 200 

Per aderire al x2y tabella di ricerca con la tabella principale DT, ho impostato la chiave DT a "x":

setkey(DT,x) 

Poi il join opere come previsto.

DT[x2y] 
# site date x y 
# 1: A 1 10 100 
# 2: B 1 10 100 
# 3: A 2 20 200 
# 4: B 2 20 200 

e posso usare "y" dalla tabella di ricerca nei calcoli o creare una nuova colonna in DT.

DT[x2y, y:=y] 
# site date x y 
# 1: A 1 10 100 
# 2: B 1 10 100 
# 3: A 2 20 200 
# 4: B 2 20 200 
# 5: A 3 30 NA 
# 6: B 3 30 NA 

Ma ora il mio serie temporali di dati DT è calettato su "x", e ho bisogno di impostare la chiave torna a "sito, la data" per un ulteriore uso.

setkey(DT,site,date) 

È questo approccio (X tasto X, unire, poi ri-key) il modo più veloce per fare questo quando DT è molto grande (righe 1M), o c'è un modo altrettanto efficace per fare questo tipo di look join, senza perdere la chiave originale sul grande tavolo DT?

+4

filari indipendenti ma 1MM è un set di dati molto piccolo, la digitazione dovrebbe richiedere meno di un secondo. Ho appena testato su 7MM ed è stato meno di un secondo. –

+1

@DavidArenburg Sì, la digitazione è veloce, ma forse significativa se eseguita molte volte. Una ragione per la domanda che non ho menzionato è che sto scrivendo alcune funzioni generali per fare calcoli su dataset di grandi dimensioni usando join, e sarebbe preferibile se le funzioni non cambiassero le chiavi o l'ordine dei dati. come argomenti, a meno che le colonne chiave non cambino naturalmente. –

+1

Sì, ho capito. Ho menzionato il suo non correlato. Anche se un uccellino mi ha sussurrato che la tua richiesta è nella lista dei progetti degli sviluppatori di 'data.table'. –

risposta

4

Con i tasti secondari effettuati (dal v1.9.6) e la recente correzione del bug sul mantenimento/scartando le chiavi correttamente (in v1.9.7), ora è possibile farlo usando on=:

# join 
DT[x2y, on="x"] # key is removed as row order gets changed. 

# update using joins 
DT[x2y, y:=y, on="x"] # key is retained, as row order isn't changed. 
7

Aggiornamento: Grazie a una correzione di bug, questo non è più necessario. Si prega di vedere la risposta accettata.


Vorrei unire appena x:

DT[,y:=x2y[J(DT$x)]$y] 

La chiave di DT viene mantenuto qui.

+2

Grazie, questo funziona per me.Attendo con impazienza una sintassi più semplice e intuitiva quando vengono implementati i join su chiavi secondarie, come menzionato da Arun. . –

+2

Ho appena controllato i tempi su questa risposta rispetto al mio OP, per un set di dati DT ordinato in ordine 2 x 1e6. Il metodo OP (setkey, join, setkey) richiede 522 ms e questa risposta richiede 251 ms. Quindi è due volte più veloce del mio approccio OP. Ho anche provato ad aggiungere set2key (DT, x) al metodo di questa risposta, e ci sono voluti 426 ms, il che significa che set2key non ha aiutato, nel presente data.table 1.9.5. –