2012-03-28 2 views
16

Gói data.table cung cấp nhiều phương thức xử lý bảng giống như SQL. Nếu một bảng có khóa, khóa đó bao gồm một hoặc nhiều cột. Nhưng một bảng không thể có nhiều hơn một khóa, bởi vì nó không thể được sắp xếp theo hai cách khác nhau cùng một lúc.Dịch SQL tham gia trên các khóa ngoài sang cú pháp R data.table

Trong ví dụ này, XYdata.table s với một cột khóa "id"; Y cũng có cột không phải là "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") 

Cú pháp sau đây sẽ tham gia các bảng trên phím của họ:

X[Y] 

Làm thế nào tôi có thể dịch các cú pháp SQL sau vào mã data.table?

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

Gần nhất mà tôi đã nhận được là:

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

Tuy nhiên, điều này không làm như vậy bên tham gia như các câu lệnh SQL.


Dưới đây là một ví dụ rõ ràng hơn, trong đó phím nước ngoài được y_id, và chúng tôi muốn tham gia để tìm kiếm giá trị của Y2 nơi 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") 

Tôi muốn tạo ra bảng:

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

tương tự như những gì được thực hiện bởi kludge sau:

> 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 

Tuy nhiên, khi tôi làm điều này:

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

Tôi không nhận được kết quả mong muốn:

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

Bạn có thể tạm thời thay đổi 'phím X2' và đặt chúng vào ' "y_id"'; sau đó thực hiện một phép nối bình thường 'Y2 [X2]' (hoặc 'X2 [Y2]' tùy thuộc vào hướng) và sau đó khôi phục khóa trước đó của 'X2'. – digEmAll

+0

@digEmAll đó là hữu ích, tôi nghĩ rằng đó là những gì 'by' đối số nào ... nhưng điều này có thể được áp dụng cho một bảng (> 2) tham gia, nơi bàn mục tiêu (trái) có> 1 khóa nước ngoài? –

+0

Tôi đồng ý với @digEmAll: 'setkey (X2, y_id)' theo sau là 'X2 [Y2, nomatch = 0]' là tất cả những gì bạn cần cho ví dụ của mình. Và điều này cũng làm việc với một số phím. Tuy nhiên, tôi không thực sự quen thuộc với cú pháp khóa ngoài trong SQL, vì vậy nếu bạn đang đấu tranh với nhiều khóa hơn, bạn có thể mở rộng ví dụ của mình không? –

Trả lời

17

Câu hỏi hay. Lưu ý những điều sau đây (phải thừa nhận là chôn) trong ?data.table:

Khi i là một data.table, x phải có một khóa. i được kết hợp với x bằng cách sử dụng phím và các hàng trong số x kết quả trùng khớp đó được trả lại. Một tham gia equi được thực hiện giữa mỗi cột trong i cho mỗi cột trong khóa của x. Trận đấu là một tìm kiếm nhị phân trong thời gian C được biên dịch trong O (log n). Nếu i có ít cột hơn số x thì nhiều hàng của x có thể khớp với mỗi hàng i. Nếu i có nhiều cột hơn x, thì các cột của i không tham gia vào kết nối được bao gồm trong kết quả. Nếu i cũng có một khóa, đó là các cột chính của i được sử dụng để đối sánh với các cột chính của x và kết hợp nhị phân của hai bảng được thực hiện.

Vì vậy, khóa ở đây là i không cần phải được khóa. Chỉ có x phải được khóa.

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 

hay,

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

cảm ơn. nhưng 'giống hệt nhau (Y2 [J (X2 $ y_id)], Y2 [X2 $ y_id]) == TRUE', có sự khác biệt nào không? –

+0

@David Đã thay đổi dữ liệu mẫu để làm cho dữ liệu rõ ràng hơn. Dữ liệu ví dụ trước có giá trị khóa giống với số hàng tức là '1: 5'. –