2010-02-09 6 views
43

Hinweis: Diese Frage und die folgenden Antworten beziehen sich auf data.table-Versionen < 1.5.3; v. 1.5.3 wurde im Februar 2011 veröffentlicht, um dieses Problem zu lösen. siehe aktuellere Behandlung (03-2012): Translating SQL joins on foreign keys to R data.table syntaxSo führen Sie eine data.table-Zusammenführungsoperation aus


Ich habe für die data.table package durch die Dokumentation Graben (Ersatz für data.frame, die für bestimmte Operationen wesentlich effizienter ist), einschließlich Josh Reich's presentation on SQL and data.table at the NYC R Meetup (pdf), aber kann diese völlig triviale Operation nicht herausfinden.

> x <- DT(a=1:3, b=2:4, key='a') 
> x 
    a b 
[1,] 1 2 
[2,] 2 3 
[3,] 3 4 
> y <- DT(a=1:3, c=c('a','b','c'), key='a') 
> y 
    a c 
[1,] 1 a 
[2,] 2 b 
[3,] 3 c 
> x[y] 
    a b 
[1,] 1 2 
[2,] 2 3 
[3,] 3 4 
> merge(x,y) 
    a b c 
1 1 2 a 
2 2 3 b 
3 3 4 c 

Die docs sagen: „Wenn [das erste Argument] ist selbst ein data.table, ein ähnliches aufgerufen Join basieren :: merge aber verwendet binäre Suche auf dem sortierten Schlüssel.“ Dies ist eindeutig nicht der Fall. Kann ich die anderen Spalten von y in das Ergebnis von x [y] mit data.tables bringen? Es scheint, als ob es nur die Reihen von x nimmt, wo der Schlüssel dem Schlüssel von y entspricht, aber den Rest von y ganz ignorierst ...

+2

Dies wurde durch v1.5.3 gelöst, das im Februar 2011 an CRAN freigegeben wurde. Bitte lesen Sie NEWS, neue? Data.table und korrigierte FAQ. –

Antwort

27

Sie zitieren den falschen Teil der Dokumentation. Wenn Sie einen Blick auf die doc von [.data.table haben Sie gelesen:

Wenn ich ein data.table ist, muss x eine Schlüssel, i x und Rückkehr die Zeilen in x Sinn kommen, die passen. Ein equi-join wird zwischen jeder Spalte in i zu jeder Spalte in x-Taste der Reihe nach ausgeführt. Dies ist ähnlich R Funktionalität von subsetting eine Matrix mit einer 2-Säulen-Matrix und in höheren Dimensionen subsetting ein n-dimensionales Array durch eine n-Spalten-Matrix

I das zugeben zu stützen Die Beschreibung des Pakets (der Teil, den Sie zitiert haben) ist etwas verwirrend, weil es scheint, dass die "[" -Operation verwendet werden kann, anstatt zu fusionieren. Aber ich denke, was es sagt ist: wenn x und y beide data.tables sind, benutzen wir einen Join auf einem Index (der wie Merge aufgerufen wird) anstelle der binären Suche.


Eine weitere Sache:

Die data.table Bibliothek, die ich über install.packages installiert wurde die merge.data.table method fehlt, so merge mit merge.data.frame nennen würde. Nach der Installation der package from R-Forge R verwendet die schnellere merge.data.table Methode.

Sie können überprüfen, ob Sie die merge.data.table Methode haben, indem die Ausgabe der Überprüfung:

methods(generic.function="merge") 

EDIT [Antwort nicht mehr gültig]: Diese Antwort bezieht sich auf data.table Version 1.3. In Version 1.5.3 hat sich das Verhalten von data.table geändert und x [y] gibt die erwarteten Ergebnisse zurück. Danke Matthew Dowle, Autor von data.table, um dies in den Kommentaren zu zeigen.

+0

Ah. Es scheint, als ob die Version auf CRAN Version 1.2 ist, während die Version auf R-Forge Version 1.3 ist. Die "Merge" -Methode wurde anscheinend in 1.3 hinzugefügt. Von dem, was ich bei R-Forge sehen kann, wurde die Methode vor ungefähr 8 Monaten hinzugefügt, also weiß ich nicht, warum es noch nicht bei CRAN ist! – Harlan

+5

Die X [Y] -Syntax wurde in Version 1.5.3 geändert, die im Februar 2011 an CRAN veröffentlicht wurde. Bitte beachten Sie die NEWS, die neue data.table und die korrigierten FAQ. –

3

Ich denke, dass f3lix korrekt ist und dass die Dokumentation ein wenig irreführend ist. Der Vorteil besteht darin, einen schnellen Join durchzuführen, um die Daten zu unterteilen.Schließlich müssen Sie die Funktion merge später wie in Ihrem obigen Beispiel verwenden.

Sie sehen in Josh's presentation on using data.table, dass so sein Beispiel ausgeführt wird. Er untergliedert zuerst eine der data.tables, dann führt sie eine Verschmelzung durch:

library(data.table) 
sdt <- DT(series, key='series_id') 
ddt <- DT(data, key='series_id') 
u <- sdt[ grepl('^[A-Z]{2}URN', fred_id) & !grepl('DSURN', fred_id) ] 
d <- ddt[ u, DT(min=min(value)), by='series_id', mult='all'] 
data <- merge(d,series)[,c('title','min','mean','max')] 
+0

Danke, Shane. Ich war sehr verwirrt, da ich wusste (oder dachte, ich wüsste), dass 'merge' die Vorteile von' data.table' nicht nutzen würde. – Harlan

14

Danke für die Antworten. Ich habe diesen Thread vermisst, als er ursprünglich veröffentlicht wurde. data.table ist seit Februar weitergegangen. 1.4.1 wurde vor einiger Zeit für CRAN veröffentlicht und 1.5 wird bald veröffentlicht. Zum Beispiel wurde der DT() Alias ​​durch list() ersetzt; als primitive ist es viel schneller, und data.table erbt nun von data.frame, so dass es mit paketen arbeitet, die nur data.frame wie ggplot und gitter akzeptieren, ohne irgendeine umwandlung (schneller und bequemer) erforderlich.

Ist es möglich, das data.table-Tag zu abonnieren, damit ich eine E-Mail bekomme, wenn jemand eine Frage mit diesem Tag postet? Die Datatable-Hilfe-Liste ist auf etwa 30-40 Nachrichten pro Monat angewachsen, aber ich freue mich auch hier zu antworten, wenn ich irgendeine Art von Benachrichtigung bekomme.

Matthew

+1

Hallo, danke für den Hinweis! Ja, das ist definitiv möglich. Klicken Sie auf die "data.table" -Tag-Box in der oberen rechten Ecke des Bildschirms, scrollen Sie dann nach unten, bis Sie das RSS-Symbol sehen, und verwenden Sie dies, um Fragen mit diesem Tag zu abonnieren. – Harlan

+0

Danke Harlan. Ich habe mich jetzt angemeldet. –

9

Ich denke, die base::merge Funktion nicht benötigt wird, wie mit data.table verbindet kann viel schneller sein. Z.B. siehe folgendes. Ich mache x und y data.tables mit 3-3 Spalten:

> x <- data.table(foo = 1:5, a=20:24, zoo = 5:1) 
> y <- data.table(foo = 1:5, b=30:34, boo = 10:14) 
> setkey(x, foo) 
> setkey(y, foo) 

Und fusionieren beide mit base:merge und data.table verbindet die Geschwindigkeit der Hinrichtungen zu sehen:

> system.time(merge(x,y)) 
    user system elapsed 
    0.027 0.000 0.023 
> system.time(x[,list(y,x)]) 
    user system elapsed 
    0.003 0.000 0.006 

Die Ergebnisse sind nicht identisch, wie letztere hat eine zusätzliche Spalte:

> merge(x,y) 
    foo a zoo b boo 
[1,] 1 20 5 30 10 
[2,] 2 21 4 31 11 
[3,] 3 22 3 32 12 
[4,] 4 23 2 33 13 
[5,] 5 24 1 34 14 
> x[,list(x,y)] 
    foo a zoo foo.1 b boo 
[1,] 1 20 5  1 30 10 
[2,] 2 21 4  2 31 11 
[3,] 3 22 3  3 32 12 
[4,] 4 23 2  4 33 13 
[5,] 5 24 1  5 34 14 

, die keine großen Schwierigkeiten machen könnte :)

+3

Danke, das ist interessant. Eine völlig nicht nachvollziehbare Syntax! Wenn ich das verwenden würde, könnte ich eine Funktion neu definieren, die 'function (x, y) x [, list (x, y)]' 'oder so etwas, vielleicht auch die zusätzliche Schlüsselspalte löscht ... – Harlan

+2

Ich denke, das Richtige Syntax für Joins in data.table ist eigentlich x [y] oder x [y,], dh Joins sollten den ersten Index verwenden. Dies führt zu denselben Ergebnissen wie bei der Zusammenführung. beachte, dass x [y] und y [x] nicht identisch sein müssen, d. h. wenn y Einträge in foo enthält, die nicht für x repräsentativ sind. Vielleicht habe ich etwas verpasst, aber siehe Joins in der data.table [vignette] (http://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.pdf) – cboettig

+1

oben x [, list (x, y)] hat bei mir nicht funktioniert. Ich habe versucht, x [, c (x, y)] und es hat funktioniert. Ich bin mir nicht sicher, ob es Sinn macht. – bala