2016-05-31 20 views
0

Ich verwende derzeit folgenden Code, um> 130 Datenrahmen zu verschmelzen und der Code braucht zu viele Stunden, um ausgeführt zu werden (Ich kam nie zum Abschluss bei einem so großen Datensatz, nur bei Teilmengen). Jede Tabelle hat zwei Spalten: Einheit (Zeichenfolge) und zählt (ganze Zahl). Ich fusioniere nach Einheiten.Schnelleres Zusammenführen vieler Datenrahmen in R

Gibt es eine Möglichkeit, dies leicht zu beschleunigen? Jede Tabelle/jeder Datenrahmen hat separat etwa 500.000 Zeilen und viele davon sind für diese Tabelle eindeutig. Durch das Zusammenführen mehrerer Tabellen erhält man daher schnell eine Anzahl von Zeilen des zusammengeführten Datenrahmens auf viele Millionen.

Am Ende werde ich Zeilen mit zu geringen Zusammenfassungszahlen aus meiner großen zusammengeführten Tabelle löschen, aber das tue ich nicht bis wollen, dass während der Zusammenführung mit der Reihenfolge meiner Dateien egal, dann ..

+1

Blick auf http://stackoverflow.com/questions/1299871/how-to-join-merge-data-frames-inner-outer-left-right für einige 'data.table' Lösungen (' Außen verbindet "). Dies wird wahrscheinlich schneller sein. – coffeinjunky

+0

Danke @coffeijunky. Ich habe das dplyr-Paket anhand des oben genannten Threads versucht, leider war das in meinem Fall langsamer. – Perlnika

+1

@coffeinjunky für einen der kleineren Datensätze konnte ich von 77 Sekunden auf 66 Sekunden runter kommen. Nicht magisch, aber auf jeden Fall hilfreich :) – Perlnika

Antwort

3

Hier einen kleinen Vergleich, zunächst mit einer eher kleinen Datenmenge, dann wäre mit einem größeren:

library(data.table) 
library(plyr) 
library(dplyr) 
library(microbenchmark) 

# sample size: 
n = 4e3 

# create some data.frames: 
df_list <- lapply(1:100, function(x) { 
    out <- data.frame(id = c(1:n), 
        type = sample(c("coffee", "americano", "espresso"),n, replace=T)) 
    names(out)[2] <- paste0(names(out)[2], x) 
    out}) 

# transform dfs into data.tables: 
dt_list <- lapply(df_list, function(x) { 
    out <- as.data.table(x) 
    setkey(out, "id") 
    out 
}) 

# set options to outer join for all methods:  
mymerge <- function(...) base::merge(..., by="id", all=T) 
mydplyr <- function(...) dplyr::full_join(..., by="id") 
myplyr <- function(...) plyr::join(..., by="id", type="full") 
mydt <- function(...) merge(..., by="id", all=T) 

# Compare: 
microbenchmark(base = Reduce(mymerge, df_list), 
       dplyr= Reduce(mydplyr, df_list), 
       plyr = Reduce(myplyr, df_list), 
       dt = Reduce(mydt, dt_list), times=50) 

Dies ergibt den folgend Ergebnisse:

Unit: milliseconds 
    expr  min  lq  mean median  uq  max neval cld 
    base 944.0048 956.9049 974.8875 962.9884 977.6824 1221.5301 50 c 
dplyr 316.5211 322.2476 329.6281 326.9907 332.6721 381.6222 50 a 
    plyr 2682.9981 2754.3139 2788.7470 2773.8958 2812.5717 3003.2481 50 d 
    dt 537.2613 554.3957 570.8851 560.5323 572.5592 757.6631 50 b 

Wir können sehen, dass die beiden Kandidaten dplyr und data.table sind. Das Ändern der Stichprobengröße auf 5e5 ergibt die folgenden Vergleiche, die zeigen, dass tatsächlich data.table dominiert. Beachten Sie, dass ich diesen Teil nach dem Vorschlag von @ BenBolker hinzugefügt habe.

microbenchmark(dplyr= Reduce(mydplyr, df_list), 
       dt = Reduce(mydt, dt_list), times=50) 

Unit: seconds 
expr  min  lq  mean median  uq  max neval cld 
dplyr 34.48993 34.85559 35.29132 35.11741 35.66051 36.66748 50 b 
    dt 10.89544 11.32318 11.61326 11.54414 11.87338 12.77235 50 a 
+2

vielleicht dominiert 'data.table' für größere Größen (OP möchte Frames mit 5e5 Zeilen anstelle von 4e3 zusammenführen ...) ...? –

+0

Sie hatten Recht @BenBolker, meine Stichprobengröße war zu klein. Meine Lösung aktualisiert. – coffeinjunky

Verwandte Themen