2015-02-26 10 views
9

मेरे पास दो टेबल हैं जो मैं निम्नलिखित SQL के बराबर एक साथ जुड़ना चाहूंगा, जहां मैं कई स्थितियों में शामिल हूं, न कि समानता।आर डेटा.Table कंडीशनल पर शामिल हों

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') 

मैं प्रदर्शन और लचीलापन दोनों कारणों के लिए SQL समाधान से बचना चाहता हूं। एक क्रॉस में शामिल होने के लिए भी जाता है, और उसके बाद फ़िल्टरिंग/एग्रीगेटिंग - यह एक इंटरमीडिएट टेबल बनायेगा जिसमें फ़िल्टर करने के लिए मेरे लिए बहुत सारे अनावश्यक रिकॉर्ड होंगे।

बहुत बहुत धन्यवाद!

अद्यतन - मेरा प्रारंभिक उदाहरण जल्दबाजी में किया गया था। मेरी वास्तविक समस्या में, मैं स्वयं में शामिल नहीं हो रहा हूं।

उत्तर

5

यह थोड़ा बदसूरत है, लेकिन काम करता है:

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

मैंने प्रत्येक को बेंचमार्क किया संभावित विकल्पों में से, और यह वास्तव में सबसे तेज़ हो गया। इस मामले में, मैं बदसूरत के साथ रह सकता हूँ। :) – Netbrian

9

यहाँ एक तरीका है:

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 

by=.EACHI के बारे में पढ़ने के लिए, this post पर एक नजर है (जब तक विगनेट्स पर मिलती कार्य पूरा हो जाएगा)।

HTH

+0

इसे पोस्ट करने के लिए धन्यवाद; यह कार्टेशियन उत्पाद से बचाता है। क्या ऐसा कुछ करने का कोई तरीका है, लेकिन इसके बजाय इंडेक्स कॉलम को सारांशित करना? मैंने यहां एक नया प्रश्न पूछा है: http://stackoverflow.com/questions/28761809/summarize-the-self-join-index-while-avoiding-cartesian-product-in-r-data-table – nsheff

-2

data.table के बाद से 1.9.8, ऐसे मामलों में जहां की स्थिति में शामिल होने के आराम हो सकता है के लिए, वहाँ सरल गैर सम तो जैसे वाक्य रचना में शामिल होने के लिए:

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

यह दिखाए गए परिणाम को वापस नहीं करता है [यहां] (http://stackoverflow.com/a/28748717/3817004), उदा। – Uwe

+0

क्षमा करें, हां कारण यह एक ही परिणाम वापस नहीं करता है क्योंकि दूसरी स्थिति वास्तव में 'num> = num या dtone' है। जहां तक ​​मैं देख सकता था यह वर्तमान डेटा.table में मान्य नहीं है। हालांकि, मुझे अभी भी लगता है कि उन मामलों के लिए गैर-इक्विटी जुड़ने की सुविधा का उल्लेख करना प्रासंगिक है जहां शामिल स्थितियां अधिक आराम से हैं। – nikola

+0

मैंने इसे रेखांकित करने के लिए उत्तर संपादित किया। – nikola

संबंधित मुद्दे