Der Übereinstimmungsansatz funktioniert, wenn im zweiten Datenrahmen für jeden Schlüsselwert im ersten ein eindeutiger Schlüssel vorhanden ist. Wenn der zweite Datenrahmen Duplikate enthält, sind die Übereinstimmungs- und Zusammenführungsansätze nicht identisch. Das Match ist natürlich schneller, da es nicht so viel bewirkt. Insbesondere wird nie nach doppelten Schlüsseln gesucht. (Fortsetzung nach Code)
DF1 = data.frame(a = c(1, 1, 2, 2), b = 1:4)
DF2 = data.frame(b = c(1, 2, 3, 3, 4), c = letters[1:5])
merge(DF1, DF2)
b a c
1 1 1 a
2 2 1 b
3 3 2 c
4 3 2 d
5 4 2 e
DF1$c = DF2$c[match(DF1$b, DF2$b)]
DF1$c
[1] a b c e
Levels: a b c d e
> DF1
a b c
1 1 1 a
2 1 2 b
3 2 3 c
4 2 4 e
In dem in der Frage veröffentlichten sqldf-Code scheint es, dass Indizes für die beiden Tabellen verwendet wurden, aber tatsächlich werden sie in Tabellen platziert, die überschrieben wurden, bevor die sql-Auswahl jemals ausgeführt wird, und dies erklärt teilweise, warum Es ist so langsam. Die Idee von sqldf ist, dass die Datenrahmen in Ihrer R-Sitzung die Datenbank bilden, nicht die Tabellen in sqlite. Daher sucht der Code jedes Mal, wenn er auf einen nicht qualifizierten Tabellennamen verweist, in Ihrem R-Arbeitsbereich danach - nicht in der Hauptdatenbank von sqlite. Daher wird in der angezeigten select-Anweisung d1 und d2 aus dem Arbeitsbereich in die Hauptdatenbank von sqlite eingelesen, wobei diejenigen mit den Indizes überlastet werden. Infolgedessen wird ein Join ohne Indizes ausgeführt. Wenn Sie die Versionen von d1 und d2 verwenden möchten, die sich in der Hauptdatenbank von sqlite befinden, müssen Sie sie als main.d1 und main bezeichnen. d2 und nicht als d1 und d2. Wenn Sie versuchen, die Ausführung so schnell wie möglich zu gestalten, beachten Sie, dass bei einem einfachen Join keine Indizes für beide Tabellen verwendet werden können, sodass Sie Zeit beim Erstellen eines der Indizes sparen können. Im folgenden Code veranschaulichen wir diese Punkte.
Es lohnt sich zu bemerken, dass die genaue Berechnung einen großen Unterschied machen kann, welches Paket am schnellsten ist. Zum Beispiel führen wir unten eine Zusammenführung und ein Aggregat durch. Wir sehen, dass die Ergebnisse für beide nahezu umgekehrt sind. Im ersten Beispiel vom schnellsten zum langsamsten erhalten wir: data.table, plyr, merge und sqldf, während im zweiten Beispiel sqldf, aggregat, data.table und plyr - fast das Gegenteil des ersten. Im ersten Beispiel ist sqldf 3x langsamer als data.table und im zweiten 200x schneller als plyr und 100-mal schneller als data.table. Unten zeigen wir den Eingabecode, die Ausgabezeiten für die Zusammenführung und die Ausgabezeiten für das Aggregat. Es ist auch erwähnenswert, dass sqldf auf einer Datenbank basiert und daher Objekte verarbeiten kann, die größer als R sind (wenn Sie das Argument dbname von sqldf verwenden), während die anderen Ansätze auf die Verarbeitung im Hauptspeicher beschränkt sind. Wir haben auch sqldf mit sqlite illustriert, aber es unterstützt auch die H2- und PostgreSQL-Datenbanken.
library(plyr)
library(data.table)
library(sqldf)
set.seed(123)
N <- 1e5
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))
g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(d1, g1, g2)
library(rbenchmark)
benchmark(replications = 1, order = "elapsed",
merge = merge(d1, d2),
plyr = join(d1, d2),
data.table = {
dt1 <- data.table(d1, key = "x")
dt2 <- data.table(d2, key = "x")
data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
},
sqldf = sqldf(c("create index ix1 on d1(x)",
"select * from main.d1 join d2 using(x)"))
)
set.seed(123)
N <- 1e5
g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(x=sample(N,N), y=rnorm(N), g1, g2)
benchmark(replications = 1, order = "elapsed",
aggregate = aggregate(d[c("x", "y")], d[c("g1", "g2")], mean),
data.table = {
dt <- data.table(d, key = "g1,g2")
dt[, colMeans(cbind(x, y)), by = "g1,g2"]
},
plyr = ddply(d, .(g1, g2), summarise, avx = mean(x), avy=mean(y)),
sqldf = sqldf(c("create index ix on d(g1, g2)",
"select g1, g2, avg(x), avg(y) from main.d group by g1, g2"))
)
Die Ergebnisse der beiden Benchmark-Aufrufe, die die Zusammenführungsberechnungen vergleichen, sind:
Joining by: x
test replications elapsed relative user.self sys.self user.child sys.child
3 data.table 1 0.34 1.000000 0.31 0.01 NA NA
2 plyr 1 0.44 1.294118 0.39 0.02 NA NA
1 merge 1 1.17 3.441176 1.10 0.04 NA NA
4 sqldf 1 3.34 9.823529 3.24 0.04 NA NA
Die Ausgabe des Benchmark-Aufrufs zum Vergleich der aggregierten Berechnungen lautet:
test replications elapsed relative user.self sys.self user.child sys.child
4 sqldf 1 2.81 1.000000 2.73 0.02 NA NA
1 aggregate 1 14.89 5.298932 14.89 0.00 NA NA
2 data.table 1 132.46 47.138790 131.70 0.08 NA NA
3 plyr 1 212.69 75.690391 211.57 0.56 NA NA