Dies ist eine philosophische Frage zur Join-Syntax von data.table. Ich finde immer mehr Verwendungsmöglichkeiten für data.tables, lerne aber immer noch ...
Das Join-Format X[Y]
für data.tables ist sehr präzise, praktisch und effizient, aber soweit ich das beurteilen kann, unterstützt es nur innere Joins und rechte äußere Joins. Um eine linke oder vollständige äußere Verknüpfung zu erhalten, muss ich Folgendes verwenden merge
:
X[Y, nomatch = NA]
- alle Zeilen in Y - rechter äußerer Join (Standard)X[Y, nomatch = 0]
- Nur Zeilen mit Übereinstimmungen in X und Y - Innerer Joinmerge(X, Y, all = TRUE)
- alle Zeilen von X und Y - vollständige äußere Verknüpfungmerge(X, Y, all.x = TRUE)
- alle Zeilen in X - linker äußerer Join
Es scheint mir praktisch zu sein, wenn das X[Y]
Join-Format alle 4 Arten von Joins unterstützt. Gibt es einen Grund, warum nur zwei Arten von Verknüpfungen unterstützt werden?
Für mich sind die Werte nomatch = 0
und nomatch = NA
Parameter für die ausgeführten Aktionen nicht sehr intuitiv. Es fällt mir leichter, die merge
Syntax zu verstehen und sich daran zu erinnern : all = TRUE
, all.x = TRUE
und all.y = TRUE
. Da die X[Y]
Operation merge
viel mehr ähnelt als match
, warum nicht die merge
Syntax für Verknüpfungen anstelle des match
Funktionsparameters verwenden nomatch
?
Hier sind Codebeispiele für die 4 Join-Typen:
# sample X and Y data.tables
library(data.table)
X <- data.table(t = 1:4, a = (1:4)^2)
setkey(X, t)
X
# t a
# 1: 1 1
# 2: 2 4
# 3: 3 9
# 4: 4 16
Y <- data.table(t = 3:6, b = (3:6)^2)
setkey(Y, t)
Y
# t b
# 1: 3 9
# 2: 4 16
# 3: 5 25
# 4: 6 36
# all rows from Y - right outer join
X[Y] # default
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
X[Y, nomatch = NA] # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
merge(X, Y, by = "t", all.y = TRUE) # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
identical(X[Y], merge(X, Y, by = "t", all.y = TRUE))
# [1] TRUE
# only rows in both X and Y - inner join
X[Y, nomatch = 0]
# t a b
# 1: 3 9 9
# 2: 4 16 16
merge(X, Y, by = "t") # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
merge(X, Y, by = "t", all = FALSE) # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
identical( X[Y, nomatch = 0], merge(X, Y, by = "t", all = FALSE) )
# [1] TRUE
# all rows from X - left outer join
merge(X, Y, by = "t", all.x = TRUE)
# t a b
# 1: 1 1 NA
# 2: 2 4 NA
# 3: 3 9 9
# 4: 4 16 16
# all rows from both X and Y - full outer join
merge(X, Y, by = "t", all = TRUE)
# t a b
# 1: 1 1 NA
# 2: 2 4 NA
# 3: 3 9 9
# 4: 4 16 16
# 5: 5 NA 25
# 6: 6 NA 36
Update: data.table v1.9.6 führte die on=
Syntax ein, die Ad-hoc- Verknüpfungen für andere Felder als den Primärschlüssel ermöglicht. jangoreckis Antwort auf die Frage Wie werden Datenrahmen (innen, außen, links, rechts) verbunden (zusammengeführt)? bietet einige Beispiele für zusätzliche Join-Typen, die data.table verarbeiten kann.
quelle
Y[X]
wenn Sie die linke äußere Verknüpfung von möchtenX[Y]
undrbind(Y[X],X[Y])
wenn Sie eine vollständige äußere Verknüpfungunique()
Ansatz unten für den vollständigen Join vorzuziehen istrbind(Y[X],X[Y])
, da das rbind das Kopieren der Tabelle beinhalten würde. Ist das richtig?unique(c(unique(X[,t]), unique(Y[,t]))
- dies sollte speichereffizienter sein, da nur zwei Listen kombiniert werden, die kleiner oder gleich der Anzahl der Zeilen in X und Y sind .Antworten:
Zitat aus den
data.table
FAQ 1.11 Was ist der Unterschied zwischenX[Y]
undmerge(X, Y)
?Wenn Sie eine linke äußere Verknüpfung von möchten
X[Y]
Wenn Sie eine vollständige äußere Verknüpfung wünschen
quelle
X[Y,all=T]
könnte eine elegante Möglichkeit sein, einen vollständigen äußeren Join innerhalb der data.table X [Y] -Syntax anzugeben. OderX[Y,all.x=T]
für die linke Verbindung. Ich fragte mich, warum es nicht so gestaltet war. Nur ein Gedanke.X[Y[J(unique_keys)]]
?Die Antwort von @ mnel ist genau richtig. Akzeptieren Sie diese Antwort. Dies ist nur eine Nachverfolgung, zu lang für Kommentare.
Wie mnel sagt, wird die linke / rechte äußere Verbindung durch Vertauschen
Y
undX
:Y[X]
-vs- erhaltenX[Y]
. Daher werden 3 der 4 Join-Typen in dieser Syntax unterstützt, nicht 2, iiuc.Das Hinzufügen des 4. scheint eine gute Idee zu sein. Nehmen wir an, wir fügen hinzu
full=TRUE
oderboth=TRUE
odermerge=TRUE
(nicht sicher, ob der beste Argumentname?), Dann war es mir vorher nicht in den Sinn gekommen,X[Y,j,merge=TRUE]
was aus den Gründen nach dem ABER in FAQ 1.12 nützlich wäre. Neue Feature-Anfrage jetzt hinzugefügt und hierher verlinkt, danke:FR # 2301: Fügen Sie das Argument merge = TRUE für X [Y] und Y [X] hinzu, wie dies bei merge () der Fall ist.
Neuere Versionen haben sich beschleunigt
merge.data.table
(indem Sie beispielsweise eine flache Kopie intern erstellen, um die Schlüssel effizienter einzustellen). So versuchen wir , zu bringenmerge()
undX[Y]
näher, und bieten alle Optionen Benutzer für volle Flexibilität. Beides hat Vor- und Nachteile. Eine weitere herausragende Feature-Anfrage ist:FR # 2033: Fügen Sie by.x und by.y zu merge.data.table hinzu
Wenn es noch andere gibt, lassen Sie sie bitte kommen.
Durch diesen Teil in der Frage:
Wenn Sie es vorziehen ,
merge()
Syntax und seine drei Argumenteall
,all.x
undall.y
verwenden Sie dann nur , dass stattX[Y]
. Denken Sie, es sollte alle Fälle abdecken. Oder meinten Sie , warum ist das Argument , eine einzigenomatch
in[.data.table
? Wenn ja, ist dies angesichts der häufig gestellten Fragen 2.14 nur natürlich. "Können Sie weiter erklären, warum data.table von der A [B] -Syntax in base inspiriert ist?". Nimmt aber auchnomatch
nur zwei Werte aktuell0
und anNA
. Das könnte erweitert werden, so dass ein negativer Wert etwas bedeutet, oder 12 würde bedeuten, die Werte der 12. Zeile zum Ausfüllen von NAs zu verwenden, oder könntenomatch
in Zukunft ein Vektor oder sogar selbst ein seindata.table
.Hm. Wie würde By-Without- By mit Merge = TRUE interagieren? Vielleicht sollten wir dies auf datatable-help übertragen .
quelle
join="all", join="all.x", join="all.y" and join="x.and.y"
am Rand meiner Notizen gekritzelt . Ich bin mir nicht sicher, ob das besser ist.join
so, gute Idee. Ich habe auf datatable-help gepostet, also mal sehen. Vielleicht geben Sie auchdata.table
etwas Zeit, um sich einzuleben. Haben Sie von-ohne-by noch zum Beispiel, und join geerbt Umfang ?join
Schlüsselwort hinzuzufügen , wenn ich eine Datentabelle bin :X[Y,j,join=string]
. Die möglichen Zeichenfolgenwerte für den Join werden wie folgt vorgeschlagen: 1) "all.y" und "right" -Diese "Antwort" ist ein Diskussionsvorschlag: Wie in meinem Kommentar angegeben, schlage ich vor
join
, [.data.table () einen Parameter hinzuzufügen, um zusätzliche Arten von Verknüpfungen zu aktivieren, zX[Y,j,join=string]
. Zusätzlich zu den 4 Arten von normalen Joins empfehle ich, 3 Arten von exklusiven Joins und den Cross- Join zu unterstützen.Die
join
Zeichenfolgenwerte (und Aliase) für die verschiedenen Verknüpfungstypen lauten wie folgt:"all.y"
und"right"
- Rechtsverknüpfung, der aktuelle Standardwert für data.table (nomatch = NA) - alle Y-Zeilen mit NAs, bei denen keine X-Übereinstimmung vorliegt;"both"
und"inner"
- innerer Join (nomatch = 0) - nur Zeilen, in denen X und Y übereinstimmen;"all.x"
und"left"
- linker Join - alle Zeilen von X, NAs, bei denen kein Y übereinstimmt:"outer"
und"full"
- vollständige äußere Verknüpfung - alle Zeilen von X und Y, NAs, bei denen keine Übereinstimmung vorliegt"only.x"
und"not.y"
- Nicht-Join- oder Anti-Join-Rückgabe von X-Zeilen, bei denen keine Y-Übereinstimmung vorliegt"only.y"
und"not.x"
- Nicht-Join- oder Anti-Join-Rückgabe von Y-Zeilen, bei denen keine X-Übereinstimmung vorliegt"not.both"
- Exklusiver Join, der X- und Y-Zeilen zurückgibt, bei denen keine Übereinstimmung mit der anderen Tabelle besteht, dh ein Exklusiv-Oder (XOR)"cross"
- Cross Join oder kartesisches Produkt, wobei jede X-Reihe mit jeder Y-Reihe übereinstimmtDer Standardwert
join="all.y"
entspricht dem aktuellen Standardwert.Die Zeichenfolgenwerte "all", "all.x" und "all.y" entsprechen den
merge()
Parametern. Die Zeichenfolgen "rechts", "links", "innen" und "außen" sind für SQL-Benutzer möglicherweise besser geeignet.Die Zeichenfolgen "beide" und "nicht beide" sind im Moment mein bester Vorschlag - aber jemand hat möglicherweise bessere Zeichenfolgenvorschläge für den inneren Join und den exklusiven Join. (Ich bin nicht sicher, ob "exklusiv" die richtige Terminologie ist. Korrigieren Sie mich, wenn es einen richtigen Begriff für einen "XOR" -Verbindung gibt.)
Die Verwendung von
join="not.y"
ist eine Alternative fürX[-Y,j]
oderX[!Y,j]
ohne Join-Syntax und möglicherweise klarer (für mich), obwohl ich nicht sicher bin, ob sie identisch sind (neue Funktion in data.table Version 1.8.3).Der Cross Join kann manchmal nützlich sein, passt aber möglicherweise nicht in das Paradigma data.table.
quelle
join
aber wenn es nicht auf den Tracker gelangt, wird es vergessen.