2015-08-14 10 views
14

मैं rolling joins को data.table में समझने की कोशिश कर रहा हूं। इसे पुन: पेश करने के लिए डेटा अंत में दिया जाता है।डुप्लिकेट कुंजियों के साथ डेटा.table पर रोलिंग

एक हवाई अड्डे पर लेनदेन के एक data.table को देखते हुए, एक निश्चित समय पर:

> dt 
    t_id airport thisTime 
1: 1  a  5.1 
2: 3  a  5.1 
3: 2  a  6.2 

(ध्यान दें 3 एक ही हवाई अड्डे और समय)

और उड़ानों की एक लुकअप तालिका हवाई अड्डों से प्रस्थान:

> dt_lookup 
    f_id airport thisTime 
1: 1  a  6 
2: 2  a  6 
3: 1  b  7 
4: 1  c  8 
5: 2  d  7 
6: 1  d  9 
7: 2  e  8 

> tables() 
    NAME  NROW NCOL MB COLS     KEY    
[1,] dt   3 3 1 t_id,airport,thisTime airport,thisTime 
[2,] dt_lookup 7 3 1 f_id,airport,thisTime airport,thisTime 

मुझे लगता है कि हवाई अड्डे से प्रस्थान सब अगले संभव उड़ानों के सभी लेनदेन मैच के लिए चाहते हैं, देने के लिए:

t_id airport thisTime f_id 
     1  a  6 1 
     1  a  6 2 
     3  a  6 1 
     3  a  6 2 

तो मैंने सोचा कि यह काम करेगा:

> dt[dt_lookup, nomatch=0,roll=Inf] 
    t_id airport thisTime f_id 
1: 3  a  6 1 
2: 3  a  6 2 

लेकिन यह लेन-देन t_id == 1 वापस नहीं आया।

the documentation से यह कहते हैं:

आमतौर पर, एक्स के प्रमुख में कोई डुप्लिकेट, वहाँ होना चाहिए ...

हालांकि, मैं अपने 'एक्स कुंजी' में डुप्लिकेट है (अर्थात् airport & thisTime), और t_id = 1 का अर्थ आउटपुट से हटाए जाने पर क्या हो रहा है/समझ नहीं सकता है।

क्या कोई भी प्रकाश डाल सकता है कि क्यों t_id = 1 वापस नहीं किया गया है, और जब मैं डुप्लिकेट करता हूं तो मैं कैसे काम में शामिल हो सकता हूं?

डाटा

library(data.table) 
dt <- data.table(t_id = seq(1:3), 
       airport = c("a","a","a"), 
       thisTime = c(5.1,6.2, 5.1), key=c("airport","thisTime")) 

dt_lookup <- data.table(f_id = c(rep(1,4),rep(2,3)), 
         airport = c("a","b","c","d", 
           "a","d","e"), 
         thisTime = c(6,7,8,9, 
           6,7,8), key=c("airport","thisTime")) 

उत्तर

21

कारण यह है कि t_id = 1 दिखाई नहीं करता है क्योंकि एक रोलिंग में शामिल होने में उत्पादन होता है पंक्ति जहां कुंजी संयोजन पिछले होती है लेता है। प्रलेखन (जोर मेरा) से:

पिछले शामिल होने के स्तंभ, आम तौर पर एक तिथि पर लागू होता है, लेकिन किसी भी आदेश दिया चर, अनियमित और सहित अंतराल हो सकता है। यदि रोल = TRUE और i पंक्ति मिलान के आखिरी एक्स में कॉलम के साथ मेल खाता है, और में इसका मान आखिरकार कॉलम में एक अंतर में गिरता है (उस समूह के लिए x में अंतिम अवलोकन के बाद), तो प्रचलित मूल्य एक्स में आगे घुमाया गया है। यह ऑपरेशन एक संशोधित बाइनरी खोज का उपयोग करके विशेष रूप से तेज़ है। ऑपरेशन को अंतिम अवलोकन के रूप में भी जाना जाता है आगे (LOCF)।

के कुछ हद तक बड़े डेटासेट पर विचार करें:

> DT 
    t_id airport thisTime 
1: 1  a  5.1 
2: 4  a  5.1 
3: 3  a  5.1 
4: 2  d  6.2 
5: 5  d  6.2 
> DT_LU 
    f_id airport thisTime 
1: 1  a  6 
2: 2  a  6 
3: 2  a  8 
4: 1  b  7 
5: 1  c  8 
6: 2  d  7 
7: 1  d  9 

जब आप एक रोलिंग प्रदर्शन सिर्फ अपने प्रश्न में की तरह शामिल हो:

DT[DT_LU, nomatch=0, roll=Inf] 

आपको मिलेगा:

t_id airport thisTime f_id 
1: 3  a  6 1 
2: 3  a  6 2 
3: 3  a  8 2 
4: 5  d  7 2 
5: 5  d  9 1 

के रूप में आप दोनों कुंजी से देख सकते हैं संयोजन a, 5.1 और d, 6.2 अंतिम पंक्ति का उपयोग शामिल डेटाटेबल के लिए किया जाता है। चूंकि आप रोल-वैल्यू के रूप में Inf का उपयोग करते हैं, इसलिए सभी भविष्य के मूल्य परिणामी डेटाटेबल में शामिल किए जाते हैं। जब आप का उपयोग करें:

DT[DT_LU, nomatch=0, roll=1] 

आप देखते हैं कि भविष्य में केवल प्रथम मान शामिल है:

t_id airport thisTime f_id 
1: 3  a  6 1 
2: 3  a  6 2 
3: 5  d  7 2 

आप airport & thisTime जहां के सभी संयोजनों के लिए के लिए चाहते हैं f_id की DT$thisTimeDT_LU$thisTime से कम है, तो आपके माध्यम से एक नया चर (या मौजूदा thisTime को प्रतिस्थापित करके) प्राप्त कर सकते हैंसमारोह। एक उदाहरण है जहाँ मैं एक नया वेरिएबल thisTime2 बनाने और उसके बाद एक सामान्य DT_LU के साथ शामिल है:

DT[, thisTime2 := ceiling(thisTime)] 
setkey(DT, airport, thisTime2)[DT_LU, nomatch=0] 

जो देता है:

> dt[, thisTime2 := ceiling(thisTime)] 
> setkey(dt, airport, thisTime2)[dt_lookup, nomatch=0] 

    t_id airport thisTime thisTime2 f_id 
1: 1  a  5.1   6 1 
2: 3  a  5.1   6 1 
3: 1  a  5.1   6 2 
4: 3  a  5.1   6 2 

:

t_id airport thisTime thisTime2 f_id 
1: 1  a  5.1   6 1 
2: 4  a  5.1   6 1 
3: 3  a  5.1   6 1 
4: 1  a  5.1   6 2 
5: 4  a  5.1   6 2 
6: 3  a  5.1   6 2 
7: 2  d  6.2   7 2 
8: 5  d  6.2   7 2 

डेटा आपके द्वारा दी गई पर लागू होती है

जब आप केवल पहले ओ के बजाय भविष्य के मूल्यों को शामिल करना चाहते हैं

: ne, तो आप थोड़ा अलग ढंग जिसके लिए आप i.col कार्यक्षमता (जो अभी तक दर्ज नहीं किया गया है) की आवश्यकता होगी की जरूरत है

setkey(DT, airport) 
setkey(DT_LU, airport) 

: पहले ही airport कॉलम के लिए कुंजी सेट 2: आप क्या चाहते हैं पाने के लिए इस प्रकार j में i.col कार्यक्षमता (जो अभी तक दर्ज नहीं किया गया है) का उपयोग करें:

DT1 <- DT_LU[DT, .(tid = i.t_id, 
        tTime = i.thisTime, 
        fTime = thisTime[i.thisTime < thisTime], 
        fid = f_id[i.thisTime < thisTime]), 
      by=.EACHI] 
जब आप दो datatables शामिल हो रहे हैं जहां एक ही COLUMNNAMES i. साथ COLUMNNAMES पूर्ववर्ती द्वारा उपयोग किया जाता i में, आप datatable के स्तंभों का उल्लेख कर सकते मामले में: 363,210

यह आप देता है:

> DT1 
    airport tid tTime fTime fid 
1:  a 1 5.1  6 1 
2:  a 1 5.1  6 2 
3:  a 1 5.1  8 2 
4:  a 4 5.1  6 1 
5:  a 4 5.1  6 2 
6:  a 4 5.1  8 2 
7:  a 3 5.1  6 1 
8:  a 3 5.1  6 2 
9:  a 3 5.1  8 2 
10:  d 2 6.2  7 2 
11:  d 2 6.2  9 1 
12:  d 5 6.2  7 2 
13:  d 5 6.2  9 1 

कुछ स्पष्टीकरण। अब thisTimeDT से thisTimeDT_LU से तुलना करना संभव है।by = .EACHI के साथ आप आश्वस्त करते हैं कि स्थिति के साथ सभी संयोजनों को परिणामस्वरूप डेटाटेबल में शामिल किया गया है।

वैकल्पिक रूप से, आप प्राप्त कर सकते हैं के साथ एक ही:

DT2 <- DT_LU[DT, .(airport=i.airport, 
        tid=i.t_id, 
        tTime=i.thisTime, 
        fTime=thisTime[i.thisTime < thisTime], 
        fid=f_id[i.thisTime < thisTime]), 
      allow.cartesian=TRUE] 

जो एक ही परिणाम देता है:

> identical(DT1, DT2) 
[1] TRUE 

आप केवल एक निश्चित सीमा के भीतर भविष्य मान शामिल करना चाहते हैं, तो आप उपयोग कर सकते हैं:

DT1 <- DT_LU[DT, 
      { 
       idx = i.thisTime < thisTime & thisTime - i.thisTime < 2 
       .(tid = i.t_id, 
       tTime = i.thisTime, 
       fTime = thisTime[idx], 
       fid = f_id[idx]) 
       }, 
      by=.EACHI] 

देता है:

> DT1 
    airport tid tTime fTime fid 
1:  a 1 5.1  6 1 
2:  a 1 5.1  6 2 
3:  a 4 5.1  6 1 
4:  a 4 5.1  6 2 
5:  a 3 5.1  6 1 
6:  a 3 5.1  6 2 
7:  d 2 6.2  7 2 
8:  d 5 6.2  7 2 

जब आप पिछले परिणाम की तुलना करते हैं, तो आप देखते हैं कि अब पंक्तियां 3, 6, 9, 10 और 12 हटा दी गई हैं।


डाटा:

DT <- data.table(t_id = c(1,4,2,3,5), 
       airport = c("a","a","d","a","d"), 
       thisTime = c(5.1, 5.1, 6.2, 5.1, 6.2), 
       key=c("airport","thisTime")) 

DT_LU <- data.table(f_id = c(rep(1,4),rep(2,3)), 
        airport = c("a","b","c","d","a","d","e"), 
        thisTime = c(6,7,8,9,6,7,8), 
        key=c("airport","thisTime")) 
+2

अच्छा इस पोस्ट को देखने के लिए। मैं कुछ समय के लिए यह कोशिश कर रहा था .. – akrun

+0

ग्रेट स्पष्टीकरण - "एक रोलिंग जॉइन उस पंक्ति को लेता है जहां कुंजी संयोजन आखिरी होता है" - मेरी समझ के लिए कुंजी धन्यवाद था। – tospig

+0

और आपकी 'छत' उदाहरण इस स्थिति में अच्छी तरह से काम करता है, लेकिन मुझे उम्मीद है कि यह काम नहीं करेगा जब 'dt $ thisTime2' मान' 1' समय इकाई से अधिक 'dt_lookup $ thisTime' मान से मेल खाता है जो मिलान करने का प्रयास कर रहा है करने के लिए, तो मुझे एक विकल्प के साथ आना पड़ सकता है? – tospig

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