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.
unique()
Ansatz unten für den vollständigen Join vorzuziehen ist rbind(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 .
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üpfung