2012-03-28 20 views
16

Pakiet data.table zapewnia wiele takich samych metod obsługi tabel, jak SQL. Jeśli tabela ma klucz, ten klucz składa się z co najmniej jednej kolumny. Ale tabela nie może mieć więcej niż jednego klucza, ponieważ nie może być posortowana na dwa różne sposoby w tym samym czasie.Tłumaczenie połączeń SQL na klucze obce na składnię R data.table

W tym przykładzie X i Y s są data.table s z jedną kolumną klucza "id"; Y ma również niepustą kolumnę "x_id".

X <- data.table(id = 1:5, a=4:8,key="id") 
    Y <- data.table(id = c(1,1, 3,5,7), x_id=c(1,4:1), key="id") 

Następująca składnia byłoby połączyć tabele na ich klucze:

X[Y] 

Jak Mogę przetłumaczyć następujące SQL składni do kodu data.table?

select * from X join Y on X.id = Y.x_id; 

Najbliżej że mam zdobyć to:

Y[X,list(id, x_id),by = x_id,nomatch=0] 

to jednak nie to samo sprzężenie wewnętrzne jak SQL.


Oto bardziej wyraźnym przykładem, w którym klucz obcy jest y_id i chcemy dołączyć do wyszukania wartości Y2 gdzie X2$y_id = Y2$id.

X2 <- data.table(id = 1:5, y_id = c(1,1,2,2,2), key="id") 
    Y2 <- data.table(id = 1:5, b = letters[1:5], key="id") 

chciałbym produkować tabeli:

id y_id b 
    1  1 "a" 
    2  1 "a" 
    3  2 "b" 
    4  2 "b" 
    5  2 "b" 

podobny do tego, co odbywa się według następującego kludge:

> merge(data.frame(X2), data.frame(Y2), by.x = "y_id", by.y = "id") 
    y_id id b 
1 1 1 a 
2 1 2 a 
3 2 3 b 
4 2 4 b 
5 2 5 b 

Jednak, kiedy to zrobić:

X2[Y2, 1:2,by = y_id] 

Nie otrzymuję pożądanego rezultatu:

y_id V1 
[1,] 1 1 
[2,] 1 2 
[3,] 2 1 
[4,] 2 2 
+2

można czasowo zmienić 'klucze X2' i ustawić je na' "y_id" '; następnie wykonaj normalne połączenie 'Y2 [X2]' (lub 'X2 [Y2]' w zależności od kierunku), a następnie przywróć poprzedni klucz 'X2'. – digEmAll

+0

@digEmAll, który jest przydatny, myślałem, że to jest to, co robi argument 'by' ... ale czy można to zastosować do wielokrotnego łączenia (> 2) tabeli, gdzie tabela docelowa (po lewej) ma> 1 klucz obcy? –

+0

Zgadzam się z @digEmAll: 'setkey (X2, y_id)', po którym następuje 'X2 [Y2, nomatch = 0]' jest wszystkim czego potrzebujesz dla twojego przykładu. A to powinno działać również z kilkoma klawiszami. Jednak nie jestem obeznany ze składnią klucza obcego w SQL, więc jeśli zmagasz się z większą liczbą kluczy, czy mógłbyś rozszerzyć swój przykład? –

Odpowiedz

17

Dobre pytanie. Uwaga Następujące (wprawdzie zakopane) w ?data.table:

Kiedy i jest data.table, x musi mieć klucz. i jest dołączone do x za pomocą klucza i wierszy w x, które są zwracane. Równoległe połączenie jest wykonywane między każdą kolumną w i dla każdej kolumny w kluczu x. Dopasowanie jest wyszukiwaniem binarnym w skompilowanym czasie C w O (log n). Jeśli i ma mniej kolumn niż klucz x, wiele wierszy z x może pasować do każdego wiersza i. Jeśli i ma więcej kolumn niż klucz x, kolumny wyniku i nie biorące udziału w łączeniu są uwzględniane w wyniku. Jeśli i ma również klucz, jest to klucz kolumn o numerze i, które są używane do dopasowania do kolumn klucza x i przeprowadzane jest binarne scalanie dwóch tabel.

Kluczem tutaj jest to, że i nie musi być kluczowany. Tylko x musi być kluczowany.

X2 <- data.table(id = 11:15, y_id = c(14,14,11,12,12), key="id") 
    id y_id 
[1,] 11 14 
[2,] 12 14 
[3,] 13 11 
[4,] 14 12 
[5,] 15 12 
Y2 <- data.table(id = 11:15, b = letters[1:5], key="id") 
    id b 
[1,] 11 a 
[2,] 12 b 
[3,] 13 c 
[4,] 14 d 
[5,] 15 e 
Y2[J(X2$y_id)] # binary search for each item of (unsorted and unkeyed) i 
    id b 
[1,] 14 d 
[2,] 14 d 
[3,] 11 a 
[4,] 12 b 
[5,] 12 b 

lub

Y2[SJ(X2$y_id)] # binary merge of keyed i, see ?SJ 
    id b 
[1,] 11 a 
[2,] 12 b 
[3,] 12 b 
[4,] 14 d 
[5,] 14 d 

identical(Y2[J(X2$y_id)], Y2[X2$y_id]) 
[1] FALSE 
+0

dzięki. ale 'identyczne (Y2 [J (X2 $ y_id)], Y2 [X2 $ y_id]) == TRUE', czy istnieje różnica? –

+0

@David Zmieniłem dane przykładowe, aby były jaśniejsze. Poprzednie dane przykładowe miały kluczowe wartości takie same jak liczby wierszy, tj. "1: 5". –