2015-02-26 17 views
9

Tôi có hai bảng mà tôi muốn tham gia với nhau theo cách tương đương với SQL sau, nơi tôi tham gia vào nhiều điều kiện, không chỉ là bình đẳng.R Data.Table Tham gia vào điều kiện

require(sqldf) 
require(data.table) 

dt <- data.table(num=c(1, 2, 3, 4, 5, 6), 
char=c('A', 'A', 'A', 'B', 'B', 'B'), 
bool=c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE)) 

dt_two <- data.table(
num =c(6, 1, 5, 2, 4, 3), 
char=c('A', 'A', 'A', 'B', 'B', 'B'), 
bool=c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE)) 


dt_out_sql <- sqldf(' 
    select dtone.num, dtone.char, dtone.bool, SUM(dttwo.num) as SUM, 
    MIN(dttwo.num) as MIN 
    from dt as dtone INNER join dt_two as dttwo on 
    (dtone.char = dttwo.char) and 
    (dtone.num >= dttwo.num OR dtone.bool) 
GROUP BY dtone.num, dtone.char, dtone.bool') 

Tôi muốn tránh giải pháp SQL, vì cả lý do hiệu suất và tính linh hoạt. Cũng vậy khi thực hiện một phép nối chéo, và sau đó lọc/tổng hợp - nó sẽ tạo ra một bảng trung gian với nhiều bản ghi không cần thiết để tôi lọc ra.

Cảm ơn bạn rất nhiều!

Cập nhật - ví dụ ban đầu của tôi đã được thực hiện trong sự vội vàng. Trong vấn đề thực tế của tôi, tôi không tự tham gia.

Trả lời

5

Đó là một chút xấu xí nhưng hoạt động:

library(data.table) 
library(sqldf) 

dt <- data.table(num=c(1, 2, 3, 4, 5, 6), 
       char=c('A', 'A', 'A', 'B', 'B', 'B'), 
       bool=c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE)) 

dt_two <- data.table(
    num =c(6, 1, 5, 2, 4, 3), 
    char=c('A', 'A', 'A', 'B', 'B', 'B'), 
    bool=c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE)) 


dt_out_sql <- sqldf(' 
    select dtone.num, 
      dtone.char, 
      dtone.bool, 
      SUM(dttwo.num) as SUM, 
      MIN(dttwo.num) as MIN 
    from dt as dtone 
    INNER join dt_two as dttwo on 
      (dtone.char = dttwo.char) and 
      (dtone.num >= dttwo.num OR dtone.bool) 
    GROUP BY dtone.num, dtone.char, dtone.bool 
    ') 

setDT(dt_out_sql) 

setkey(dt, char) 
setkey(dt_two, char) 

dt_out_r <- dt[dt_two, 
       list(dtone.num = num, 
        dttwo.num = i.num, 
        char, 
        bool) , 
       nomatch = 0, allow.cartesian = T 
       ][ 
       dtone.num >= dttwo.num | bool, 
       list(SUM = sum(dttwo.num), 
         MIN = min(dttwo.num)), 
       by = list(num = dtone.num, 
          char, 
          bool) 
       ] 

setkey(dt_out_r, num, char, bool) 


all.equal(dt_out_sql, dt_out_r, check.attributes = FALSE) 
+1

Tôi đã đánh giá từng câu hỏi của các tùy chọn có thể, và điều này thực sự hóa ra là nhanh nhất. Trong trường hợp này, tôi có thể sống với xấu xí. :) – Netbrian

9

Dưới đây là một cách:

require(data.table) 
setkey(dt, char) 
setkey(dt_two, char) 

dt_two[dt, { 
    val = num[i.bool | i.num >= num]; 
    list(num=i.num, bool=i.bool, sum=sum(val), min=min(val)) 
}, by=.EACHI] 
# char num bool sum min 
# 1: A 1 TRUE 12 1 
# 2: A 2 FALSE 1 1 
# 3: A 3 TRUE 12 1 
# 4: B 4 FALSE 9 2 
# 5: B 5 TRUE 9 2 
# 6: B 6 FALSE 9 2 

Để đọc về by=.EACHI, có một cái nhìn tại this post (cho đến họa tiết trên tham gia là thành phẩm).

HTH

+0

cảm ơn bạn đã đăng bài này; nó tránh được sản phẩm Descartes. Có cách nào để làm một cái gì đó tương tự, nhưng thay vào đó tóm tắt cột chỉ mục? Tôi đã hỏi một câu hỏi mới ở đây: http://stackoverflow.com/questions/28761809/summarize-the-self-join-index-while-avoiding-cartesian-product-in-r-data-table – nsheff

-2

Kể từ data.table 1.9.8, đối với trường hợp điều kiện tham gia có thể được thư giãn, có đơn giản không equi tham gia cú pháp như sau:

dt_two[dt, on=.(char, num >= num)] 
+0

Điều này không trả lại kết quả mong đợi như được hiển thị [ở đây] (http://stackoverflow.com/a/28748717/3817004), ví dụ: – Uwe

+0

Xin lỗi, có lý do không trả lại kết quả tương tự là vì điều kiện thứ hai thực sự là 'num> = num OR dtone'. Theo như tôi có thể thấy điều này là không hợp lệ trong data.table hiện tại. Tuy nhiên, tôi vẫn nghĩ rằng nó có liên quan đến đề cập đến tính năng tham gia không equi cho các trường hợp mà các điều kiện tham gia được thoải mái hơn. – nikola

+0

Tôi đã chỉnh sửa câu trả lời để nhấn mạnh điều này. – nikola

Các vấn đề liên quan