2016-02-05 7 views
6

या अधिक सामान्य होने के लिए, यह DT[,.SD[...],by=...] बनाम merge(aggregate(...)) है।आर: डेटा.table बनाम विलय (कुल()) प्रदर्शन

set.seed(5141) 
size = 1e6 
df <- data.table(a = rnorm(size), 
       b = paste0(sample(letters, size, T), 
          sample(letters, size, T), 
          sample(letters, size, T)), 
       c = sample(1:(size/10), size, T), 
       d = sample(seq.Date(as.Date("2015-01-01"), 
            as.Date("2015-05-31"), by="day"), size, T)) 

system.time(df[,.SD[d == max(d)], by = c]) 
# user system elapsed 
# 50.89 0.00 51.00 
system.time(merge(aggregate(d ~ c, data = df, max), df)) 
# user system elapsed 
# 18.24 0.20 18.45 

आमतौर पर data.table प्रदर्शन के साथ कोई समस्या हो रही है, मैं इस विशिष्ट उदाहरण से हैरान हो गया:

आगे की हलचल के बिना, यहाँ डेटा और उदाहरण है। मुझे कुछ घटना प्रकारों के केवल नवीनतम (एक साथ हो सकते हैं) घटनाओं को लेकर काफी बड़े डेटा फ्रेम को सब्सट्रेट करना था। और उन विशेष घटनाओं के लिए शेष प्रासंगिक डेटा रखें। हालांकि, ऐसा लगता है कि .SD इस विशेष एप्लिकेशन में अच्छी तरह से स्केल नहीं करता है।

क्या इस तरह के कार्यों से निपटने के लिए एक बेहतर "डेटा टेबल तरीका" है?

+3

दिलचस्प बात यह है कि, 'डीएफ [, is_max: = d == अधिकतम (डी), द्वारा = सी] [is_max == टी,]' मेरी मशीन पर बहुत तेज़ चलता है। – Heroka

+0

यह अब तक का सबसे तेज़ समाधान प्रतीत होता है। क्या अतिरिक्त कॉलम बनाये बिना वही काम करना संभव होगा? –

+0

मुझे नहीं पता, आप हमेशा इसे बाद में हटा सकते हैं 'डीएफ [, is_max: = d == अधिकतम (डी), द्वारा = सी] [is_max == टी,] [, is_max: = NULL,] '। और @ अकरुन द्वारा प्रदान किया गया जॉइन-समाधान अब तक का सबसे तेज़ है। – Heroka

उत्तर

8

हम पंक्ति सूचकांक प्राप्त करने के लिए .I का उपयोग कर सकते हैं और उस पर आधारित पंक्तियों को सब्सक्राइब कर सकते हैं। यह तेज़ होना चाहिए।

system.time(df[df[,.I[d == max(d)], by = c]$V1]) 
# user system elapsed 
# 5.00 0.09 5.30 

@ Heroka के समाधान

system.time(df[,is_max:=d==max(d), by = c][is_max==T,]) 
# user system elapsed 
# 5.06 0.00 5.12 

मेरी मशीन पर aggregate विधि

system.time(merge(aggregate(d ~ c, data = df, max), df)) 
# user system elapsed 
# 48.62 1.00 50.76 

देता है .SD विकल्प

system.time(df[,.SD[d == max(d)], by = c]) 
# user system elapsed 
# 151.13 0.40 156.57 

का उपयोग के साथ

system.time(df[df[, list(d=max(d)) , c], on=c('c', 'd')]) 
# user system elapsed 
# 0.58 0.01 0.60 

शामिल होते हैं तो हम merge/aggregate और == के बीच तुलना को देखो, वे अलग अलग कार्य हैं। आम तौर पर, के साथ जुड़े हुए संवाद की तुलना में aggregate/merge विधि धीमी हो जाएगी। लेकिन, इसके बजाय हम == का उपयोग कर रहे हैं जो सब्सटिंग के लिए .SD के साथ प्रत्येक पंक्ति (कुछ समय लेता है) की तुलना करता है (जो पंक्ति अनुक्रमण के लिए .I की तुलना में अपेक्षाकृत कम कुशल है)। .SD में [.data.table का ओवरहेड भी है।

+0

मुझे लगता है कि समाधान में शामिल होने में कुछ याद आ रहा है। और संदिग्ध रूप से अच्छा परिणाम। इस बीच, मैं 'I' समाधान में देखूंगा। कोशिश करने के लिए पूरी सरणी प्रदान करने के लिए धन्यवाद। –

+0

@ एवल। यदि आप वाक्यविन्यास देखते हैं, तो मैं 'on' का उपयोग कर रहा हूं। आप छोटे डेटासेट – akrun

+0

'> nrow (df [df [, list (d = max (d)), c], = 'c'] पर समाधान का परीक्षण कर सकते हैं) [1] 1000000' –

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