2012-06-21 4 views
23

Sto cercando un metodo efficiente (sia dal punto di vista delle risorse del computer che di apprendimento/implementazione) per unire due frame di dati più grandi (dimensioni> 1 milione/300 KB file RData).Alternative efficienti da unire per i dataframes più grandi. R

"unione" in base R e "join" in plyr appaiono per consumare tutta la memoria in modo efficace bloccando il sistema.

Esempio
carico test data frame

e provare

test.merged<-merge(test, test) 

o

test.merged<-join(test, test, type="all") 
    -

Il seguente post fornisce un elenco di unione e le alternative:
How to join (merge) data frames (inner, outer, left, right)?

Di seguito consente di ispezione dimensioni dell'oggetto:
https://heuristically.wordpress.com/2010/01/04/r-memory-usage-statistics-variable/

dati prodotti da anonym

+8

sql.df o data.table? –

+0

Dopo aver svuotato le belle risposte di seguito, sono stato in grado di trovare: http://stackoverflow.com/questions/4322219/whats-the-fastest-way-to-merge-join-data-frames-in-r (anche se il la domanda non riguardava il df di grandi dimensioni, ma riguardo al salvataggio dei millisecondi, ha ottenuto risposte simili come di seguito). –

risposta

18

Ecco l'obbligatorio data.table esempio:

library(data.table) 

## Fix up your example data.frame so that the columns aren't all factors 
## (not necessary, but shows that data.table can now use numeric columns as keys) 
cols <- c(1:5, 7:10) 
test[cols] <- lapply(cols, FUN=function(X) as.numeric(as.character(test[[X]]))) 
test[11] <- as.logical(test[[11]]) 

## Create two data.tables with which to demonstrate a data.table merge 
dt <- data.table(test, key=names(test)) 
dt2 <- copy(dt) 
## Add to each one a unique non-keyed column 
dt$X <- seq_len(nrow(dt)) 
dt2$Y <- rev(seq_len(nrow(dt))) 

## Merge them based on the keyed columns (in both cases, all but the last) to ... 
## (1) create a new data.table 
dt3 <- dt[dt2] 
## (2) or (poss. minimizing memory usage), just add column Y from dt2 to dt 
dt[dt2,Y:=Y] 
+0

Grazie per l'ottima risposta. Immagino che se vuoi mantenere l'ordine originale aggiungi una colonna 1: grow (df) e usala come primo elemento della chiave? –

+0

@ EtienneLow-Décarie - Questa è una buona domanda. Penso che tu voglia aggiungere una colonna di questo tipo, ma ** non renderla ** un elemento della chiave. In questo modo puoi usarlo per riordinare i dati in qualsiasi momento. (Non dovrebbe essere parte della chiave poiché è solo un marcatore di un ordine, non un identificatore di variabile/gruppo che ha lo stesso significato in diversi set di dati). –

+2

Data.table indica la fine della necessità di applicare e plyr !? Molto impressionante! –

0

Non si deve fare l'unione in R? In caso contrario, unire i file di dati sottostanti utilizzando una semplice concatenazione di file e quindi caricarli in R. (mi rendo conto che questo potrebbe non essere applicabile alla tua situazione, ma se lo fa, potrebbe farti risparmiare un sacco di mal di testa.)

+2

Deve essere eseguito dal vivo in R poiché è un passo in una routine di ottimizzazione che scrivere sul disco potrebbe essere un collo di bottiglia. Grazie comunque. –

20

Ecco alcuni tempi per le data.table vs. data.frame metodi.
L'utilizzo di data.table è molto più veloce. Per quanto riguarda la memoria, posso segnalare informalmente che i due metodi sono molto simili (entro il 20%) nell'utilizzo della RAM.

library(data.table) 

set.seed(1234) 
n = 1e6 

data_frame_1 = data.frame(id=paste("id_", 1:n, sep=""), 
          factor1=sample(c("A", "B", "C"), n, replace=TRUE)) 
data_frame_2 = data.frame(id=sample(data_frame_1$id), 
          value1=rnorm(n)) 

data_table_1 = data.table(data_frame_1, key="id") 
data_table_2 = data.table(data_frame_2, key="id") 

system.time(df.merged <- merge(data_frame_1, data_frame_2)) 
# user system elapsed 
# 17.983 0.189 18.063 


system.time(dt.merged <- merge(data_table_1, data_table_2)) 
# user system elapsed 
# 0.729 0.099 0.821