2012-12-28 3 views
9

Suite à cet article de wikipedia SQL join Je voulais avoir une vue claire sur la façon dont nous pourrions avoir des jointures avec data.table. Dans le processus, nous avons peut-être découvert un bug en rejoignant NAs. Prenant l'exemple de wiki:data.table jointure interne/externe avec NA dans la colonne de jointure de type bug double?

R) X = data.table(name=c("Raf","Jon","Ste","Rob","Smi","Joh"),depID=c(31,33,33,34,34,NA),key="depID") 
R) Y = data.table(depID=c(31,33,34,35),depName=c("Sal","Eng","Cle","Mar"),key="depID") 
R) X 
    name depID 
1: Joh NA 
2: Raf 31 
3: Jon 33 
4: Ste 33 
5: Rob 34 
6: Smi 34 
R) Y 
    depID depName 
1: 31  Sal 
2: 33  Eng 
3: 34  Cle 
4: 35  Mar 

LEFT OUTER JOIN

R) merge.data.frame(X,Y,all.x=TRUE) 
    depID name depName 
1 31 Raf  Sal 
2 33 Jon  Eng 
3 33 Ste  Eng 
4 34 Rob  Cle 
5 34 Smi  Cle 
6 NA Joh <NA> 

merge.data.table ne produisent pas le même résultat et montrer ce que je pense est un bug sur lign 2.

R) merge(X,Y,all.x=TRUE) 
    depID name depName 
1: NA Joh  Eng 
2: 31 Raf  NA 
3: 33 Jon  Eng 
4: 33 Ste  Eng 
5: 34 Rob  Cle 
6: 34 Smi  Cle 
R) Y[X] #same -> :(
    depID depName name 
1: NA  Eng Joh 
2: 31  NA Raf 
3: 33  Eng Jon 
4: 33  Eng Ste 
5: 34  Cle Rob 
6: 34  Cle Smi 

RIGHT OUTER JOIN On dirait même

R) merge.data.frame(X,Y,all.y=TRUE) 
    depID name depName 
1 31 Raf  Sal 
2 33 Jon  Eng 
3 33 Ste  Eng 
4 34 Rob  Cle 
5 34 Smi  Cle 
6 35 <NA>  Mar 

R) merge(X,Y,all.y=TRUE) 
    depID name depName 
1: NA Joh  Eng 
2: 31 NA  Sal 
3: 33 Jon  Eng 
4: 33 Ste  Eng 
5: 34 Rob  Cle 
6: 34 Smi  Cle 
7: 35 NA  Mar 

INNER (NATUREL) REJOIGNEZ

R) merge.data.frame(X,Y) 
    depID name depName 
1 31 Raf  Sal 
2 33 Jon  Eng 
3 33 Ste  Eng 
4 34 Rob  Cle 
5 34 Smi  Cle 
R) merge(X,Y) 
    depID name depName 
1: NA Joh  Eng 
2: 33 Jon  Eng 
3: 33 Ste  Eng 
4: 34 Rob  Cle 
5: 34 Smi  Cle 

Répondre

7

Oui, il ressemble à un (embarassant) nouveau bug lié à la NA dans la clé. Il y a eu d'autres discussions à propos de NA dans la clé qui n'étaient pas possibles mais je ne me suis pas rendu compte que ça pouvait gâcher de cette façon. Va enquêter. Merci ...

#2453 NA in double key column messes up joins (NA in integer and character ok)

maintenant fixé à 1.8.7 (commit 780), de NOUVELLES:

NA dans une colonne de type de jointure à double pourrait provoquer à la fois X [Y] et de fusion (X, Y) pour retourner des résultats incorrects, # 2453. En raison d'un errant x == NA_REAL dans la source C qui aurait dû être ISNA (x). La prise en charge du double dans les jointures à clé est un ajout relativement récent à data.table, mais qui est tout de même embarrassant. Fixe et tests ajoutés. Un grand merci à statquant pour le rapport complet et reproductible.

+0

Comme il a été signalé dans un précédent, réponse supprimé (qui était vraiment un commentaire), la fusion fonctionne correctement si les colonnes depID sont des entiers. –

+0

@MatthewLundberg Intéressant, merci pour cela. Pourquoi a-t-il été supprimé, semble utile! Cela expliquerait pourquoi les tests ne l'ont pas attrapé - je n'aurais probablement pensé qu'à tester NA avec des entiers pensant que NA comme double ne ferait pas de différence. –

+0

Je ne peux pas répondre à cela, mais je ne savais pas si vous essaieriez la fusion avec des entiers sans l'indice. Le répondant a affirmé que le personnage a aussi travaillé, mais je n'ai pas vérifié. –

2

Faisant suite à des commentaires dans d'autres réponses, oui, voici la preuve que cela affecte seulement le type double colonnes (NA dans les colonnes integer et character sont ok).

X = data.table(name=c("Raf","Jon","Ste","Rob","Smi","Joh"), 
       depID=as.integer(c(31,33,33,34,34,NA)),key="depID") 
Y = data.table(depID=as.integer(c(31,33,34,35)), 
       depName=c("Sal","Eng","Cle","Mar"),key="depID") 
Y[X] 
    depID depName name 
1: NA  NA Joh 
2: 31  Sal Raf 
3: 33  Eng Jon 
4: 33  Eng Ste 
5: 34  Cle Rob 
6: 34  Cle Smi 

merge.data.frame(X,Y,all.x=T) 
    depID name depName 
1 31 Raf  Sal 
2 33 Jon  Eng 
3 33 Ste  Eng 
4 34 Rob  Cle 
5 34 Smi  Cle 
6 NA Joh <NA> 

Y = data.table(depID=as.character(c(31,33,34,35)), 
       depName=c("Sal","Eng","Cle","Mar"),key="depID") 
X = data.table(name=c("Raf","Jon","Ste","Rob","Smi","Joh"), 
       depID=as.character(c(31,33,33,34,34,NA)),key="depID") 
X 
    name depID 
1: Raf 31 
2: Jon 33 
3: Ste 33 
4: Rob 34 
5: Smi 34 
6: Joh NA 
Y 
    depID depName 
1: 31  Sal 
2: 33  Eng 
3: 34  Cle 
4: 35  Mar 
str(X) 
Classes ‘data.table’ and 'data.frame': 6 obs. of 2 variables: 
$ name : chr "Raf" "Jon" "Ste" "Rob" ... 
$ depID: chr "31" "33" "33" "34" ... 
- attr(*, "sorted")= chr "depID" 
- attr(*, ".internal.selfref")=<externalptr> 

merge.data.frame(X,Y,all.x=T) 
    depID name depName 
1 31 Raf  Sal 
2 33 Jon  Eng 
3 33 Ste  Eng 
4 34 Rob  Cle 
5 34 Smi  Cle 
6 <NA> Joh <NA> 

Y[X] 
    depID depName name 
1: 31  Sal Raf 
2: 33  Eng Jon 
3: 33  Eng Ste 
4: 34  Cle Rob 
5: 34  Cle Smi 
6: NA  NA Joh 

LE PROBLÈME EST FIXE PAR MATTHEW Dowle EN V.1.8.7

1

Quelques informations qui peuvent être utile:

library(data.table); 

X <- data.table(name=c("Raf","Jon","Ste","Rob","Smi","Joh"),depID=c(31,33,33,34,34,NA),key="depID") 
#R) X 
    #name depID 
#1: Joh NA 
#2: Raf 31 
#3: Jon 33 
#4: Ste 33 
#5: Rob 34 
#6: Smi 34 

Y <- data.table(depID=c(31,33,34,35),depName=c("Sal","Eng","Cle","Mar"),key="depID") 
#R) Y 
    #depID depName 
#1: 31  Sal 
#2: 33  Eng 
#3: 34  Cle 
#4: 35  Mar 

################# 
#LEFT OUTER JOIN# 
################# 
LJ <- merge.data.frame(X,Y,by="depID",all.x=TRUE); #by is implicit (see ?merge.data.frame) 
#R) LJ 
    #depID name depName 
#1 31 Raf  Sal 
#2 33 Jon  Eng 
#3 33 Ste  Eng 
#4 34 Rob  Cle 
#5 34 Smi  Cle 
#6 NA Joh <NA> 

LJ2 <- Y[X]; 
#R) LJ2 
    #depID depName name 
#1: NA  NA Joh 
#2: 31  Sal Raf 
#3: 33  Eng Jon 
#4: 33  Eng Ste 
#5: 34  Cle Rob 
#6: 34  Cle Smi 

################## 
#RIGHT OUTER JOIN# 
################## 
RJ <- merge.data.frame(X,Y,by="depID",all.y=TRUE); #by is implicit (see ?merge.data.frame) 
#R) RJ 
    #depID name depName 
#1 31 Raf  Sal 
#2 33 Jon  Eng 
#3 33 Ste  Eng 
#4 34 Rob  Cle 
#5 34 Smi  Cle 
#6 35 <NA>  Mar 

RJ2 <- X[Y]; 
#R) RJ2 
    #depID name depName 
#1: 31 Raf  Sal 
#2: 33 Jon  Eng 
#3: 33 Ste  Eng 
#4: 34 Rob  Cle 
#5: 34 Smi  Cle 
#6: 35 NA  Mar 

################# 
#FULL OUTER JOIN# 
################# 
FJ <- merge.data.frame(X,Y,all=T) 
#R) FJ 
    #depID name depName 
#1 31 Raf  Sal 
#2 33 Jon  Eng 
#3 33 Ste  Eng 
#4 34 Rob  Cle 
#5 34 Smi  Cle 
#6 35 <NA>  Mar 
#7 NA Joh <NA> 

FJ2 <- merge(X,Y,all=T) 
#R) FJ2 
    #depID name depName 
#1: NA Joh  NA 
#2: 31 Raf  Sal 
#3: 33 Jon  Eng 
#4: 33 Ste  Eng 
#5: 34 Rob  Cle 
#6: 34 Smi  Cle 
#7: 35 NA  Mar 

#################### 
#NATURAL INNER JOIN# 
#################### 
IJ <- merge.data.frame(X,Y) 
#R) IJ 
    #depID name depName 
#1 31 Raf  Sal 
#2 33 Jon  Eng 
#3 33 Ste  Eng 
#4 34 Rob  Cle 
#5 34 Smi  Cle 

IJ2 <- merge(X,Y) 
#R) IJ2 
    #depID name depName 
#1: 31 Raf  Sal 
#2: 33 Jon  Eng 
#3: 33 Ste  Eng 
#4: 34 Rob  Cle 
#5: 34 Smi  Cle 


A <- data.table(time=as.POSIXct(c("10:01:01","10:01:02","10:01:04","10:01:05","10:01:02","10:01:01","10:01:01"),format="%H:%M:%S"), 
       b=c("a","a","a","a","b","c","c"), 
       d=c(1,1.9,2,1.8,5,4.1,4.2)); 
B <- data.table(time=as.POSIXct(c("10:01:01","10:01:03","10:01:00","10:01:01"),format="%H:%M:%S"),b=c("a","a","c","d"), e=c(1L,2L,3L,4L)); 
setkey(A,b,time) 
setkey(B,b,time) 


########### 
#ASOF JOIN# 
########### 
AOJ <- B[A,roll=T] 
#R) AOJ 
    #b    time e d 
#1: a 2013-01-11 10:01:01 1 1.0 
#2: a 2013-01-11 10:01:02 1 1.9 
#3: a 2013-01-11 10:01:04 2 2.0 
#4: a 2013-01-11 10:01:05 2 1.8 
#5: b 2013-01-11 10:01:02 NA 5.0 
#6: c 2013-01-11 10:01:01 3 4.1 
#7: c 2013-01-11 10:01:01 3 4.2 
Questions connexes