C'est un peu une question philosophique sur la syntaxe de jointure data.table. Je trouve de plus en plus d'utilisations pour les data.tables, mais j'apprends toujours ...
Le format X[Y]
de jointure pour data.tables est très concis, pratique et efficace, mais pour autant que je sache, il ne prend en charge que les jointures internes et les jointures externes droites. Pour obtenir une jointure externe gauche ou complète, je dois utiliser merge
:
X[Y, nomatch = NA]
- toutes les lignes en Y - jointure externe droite (par défaut)X[Y, nomatch = 0]
- uniquement les lignes avec des correspondances en X et en Y - jointure internemerge(X, Y, all = TRUE)
- toutes les lignes de X et Y - jointure externe complètemerge(X, Y, all.x = TRUE)
- toutes les lignes en X - jointure externe gauche
Il me semble qu'il serait utile que le X[Y]
format de jointure prenne en charge les 4 types de jointures. Y a-t-il une raison pour laquelle seuls deux types de jointures sont pris en charge?
Pour moi, les valeurs des paramètres nomatch = 0
et nomatch = NA
ne sont pas très intuitives pour les actions effectuées. Il me est plus facile à comprendre et à mémoriser la merge
syntaxe: all = TRUE
, all.x = TRUE
et all.y = TRUE
. Puisque l' X[Y]
opération ressemble merge
beaucoup plus à match
, pourquoi ne pas utiliser la merge
syntaxe des jointures plutôt que le paramètre de la match
fonction nomatch
?
Voici des exemples de code des 4 types de jointure:
# 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
Mise à jour: data.table v1.9.6 a introduit la on=
syntaxe, qui permet des jointures ad hoc sur des champs autres que la clé primaire. réponse de jangorecki à la question Comment joindre (fusionner) des trames de données (interne, externe, gauche, droite)? fournit quelques exemples de types de jointures supplémentaires que data.table peut gérer.
la source
Y[X]
si vous voulez la jointure externe gauche deX[Y]
etrbind(Y[X],X[Y])
si vous voulez une jointure externe complèteunique()
approche ci-dessous pour la jointure complète est préférablerbind(Y[X],X[Y])
, car la rbind impliquerait de copier la table. Est-ce correct?unique(c(unique(X[,t]), unique(Y[,t]))
, cela devrait être plus efficace en mémoire car il ne combine que deux listes qui vont être inférieures ou égales au nombre de lignes dans X et Y .Réponses:
Pour citer la
data.table
FAQ 1.11 Quelle est la différence entreX[Y]
etmerge(X, Y)
?Si vous voulez une jointure externe gauche de
X[Y]
Si vous voulez une jointure externe complète
la source
X[Y,all=T]
pourrait être un moyen élégant de spécifier une jointure externe complète dans la syntaxe data.table X [Y]. OuX[Y,all.x=T]
pour la jointure gauche. Je me suis demandé pourquoi ce n'était pas conçu de cette façon. Juste une pensée.X[Y[J(unique_keys)]]
?La réponse de @ mnel est parfaite, alors acceptez cette réponse. C'est juste un suivi, trop long pour les commentaires.
Comme le dit mnel, la jointure externe gauche / droite est obtenue en échangeant
Y
etX
:Y[X]
-vs-X[Y]
. Donc, 3 des 4 types de jointure sont pris en charge dans cette syntaxe, et non 2, iiuc.L'ajout du 4ème semble une bonne idée. Disons que nous ajoutons
full=TRUE
ouboth=TRUE
oumerge=TRUE
(vous n'êtes pas sûr du meilleur nom d'argument?) Alors cela ne m'est pas venu à l'esprit avant que ceX[Y,j,merge=TRUE]
serait utile pour les raisons après le MAIS dans la FAQ 1.12. Nouvelle demande de fonctionnalité maintenant ajoutée et liée ici, merci:FR # 2301: Ajoutez l'argument merge = TRUE pour les jointures X [Y] et Y [X] comme le fait merge ().
Les versions récentes ont accéléré
merge.data.table
(en prenant une copie superficielle en interne pour définir les clés plus efficacement, par exemple). Nous essayons donc de fairemerge()
etX[Y]
plus, et de fournir toutes les options à l' utilisateur une flexibilité totale. Il y a des avantages et des inconvénients à la fois. Une autre demande de fonctionnalité exceptionnelle est:FR # 2033: Ajoutez by.x et by.y à merge.data.table
S'il y en a d'autres, veuillez les continuer à venir.
Par cette partie de la question:
Si vous préférez la
merge()
syntaxe et ses 3 argumentsall
,all.x
etall.y
puis il suffit d' utiliser qu'au lieu deX[Y]
. Je pense que cela devrait couvrir tous les cas. Ou avez - vous dire pourquoi l'argument un seulnomatch
dans[.data.table
? Si c'est le cas, c'est juste la manière qui semblait naturelle étant donné la FAQ 2.14: "Pouvez-vous expliquer plus en détail pourquoi data.table est inspiré de la syntaxe A [B] en base?". Mais aussi,nomatch
ne prend que deux valeurs actuellement0
etNA
. Cela pourrait être étendu de sorte qu'une valeur négative signifiait quelque chose, ou 12 signifierait utiliser les valeurs de la 12e ligne pour remplir les NA, par exemple, ounomatch
à l'avenir pourrait être un vecteur ou même lui-même adata.table
.Hm. Comment interagirait by-without-by avec merge = TRUE? Peut-être devrions-nous prendre cela en charge pour datatable-help .
la source
join="all", join="all.x", join="all.y" and join="x.and.y"
en marge de mes notes. Je ne sais pas si c'est mieux.join
comme ça, bonne idée. J'ai posté sur datatable-help alors voyons voir. Peut-être aussi donner undata.table
peu de temps pour vous installer. Avez-vous déjà passé par-sans-par par exemple, et également suivre une portée héritée ?join
mot - clé, quand i est un datatable:X[Y,j,join=string]
. Les valeurs de chaîne possibles pour join sont suggérées comme suit: 1) "all.y" et "right" -Cette « réponse » est une proposition de discussion: Comme indiqué dans mon commentaire, je suggère d' ajouter un
join
paramètre à [.data.table () pour permettre d' autres types de jointures, à savoir:X[Y,j,join=string]
. En plus des 4 types de jointures ordinaires, je suggère également de prendre en charge 3 types de jointures exclusives et la jointure croisée .Les
join
valeurs de chaîne (et les alias) pour les différents types de jointure sont proposées comme suit:"all.y"
et"right"
- jointure à droite, la valeur par défaut de la table data.table actuelle (nomatch = NA) - toutes les lignes Y avec NA où il n'y a pas de correspondance X;"both"
et"inner"
- jointure interne (nomatch = 0) - uniquement les lignes où X et Y correspondent;"all.x"
et"left"
- jointure gauche - toutes les lignes de X, NA où aucun Y ne correspond:"outer"
et"full"
- jointure externe complète - toutes les lignes de X et Y, NA où aucune correspondance"only.x"
et"not.y"
- non-jointure ou anti-jointure renvoyant X lignes où il n'y a pas de correspondance Y"only.y"
et"not.x"
- non-jointure ou anti-jointure renvoyant des lignes Y où il n'y a pas de correspondance X"not.both"
- jointure exclusive renvoyant des lignes X et Y où il n'y a pas de correspondance avec l'autre table, c'est-à-dire un ou exclusif (XOR)"cross"
- jointure croisée ou produit cartésien avec chaque ligne de X correspondant à chaque ligne de YLa valeur par défaut est
join="all.y"
correspond à la valeur par défaut actuelle.Les valeurs de chaîne "all", "all.x" et "all.y" correspondent à
merge()
paramètres. Les chaînes «droite», «gauche», «interne» et «externe» peuvent être plus adaptées aux utilisateurs SQL.Les chaînes "both" et "not.both" sont ma meilleure suggestion pour le moment - mais quelqu'un peut avoir de meilleures suggestions de chaînes pour la jointure interne et la jointure exclusive. (Je ne sais pas si "exclusif" est la bonne terminologie, corrigez-moi s'il existe un terme approprié pour une jointure "XOR".)
L'utilisation de
join="not.y"
est une alternative pour la syntaxeX[-Y,j]
ouX[!Y,j]
non-join et peut-être plus claire (pour moi), même si je ne suis pas sûr si elles sont identiques (nouvelle fonctionnalité de data.table version 1.8.3).La jointure croisée peut parfois être pratique, mais elle ne rentre pas dans le paradigme data.table.
la source
join
mais à moins qu'il n'atteigne le tracker, il sera oublié.