2012-07-26 18 views
43

डेटा.table पैकेज के साथ एक स्लाइडिंग विंडो फ़ंक्शन को लागू करने का सबसे अच्छा (सबसे तेज़ तरीका) क्या है?आर डेटाटेबल स्लाइडिंग विंडो

मैं रोलिंग औसत की गणना करने की कोशिश कर रहा हूं लेकिन प्रति दिन कई पंक्तियां हैं (2 अतिरिक्त कारकों के कारण), जो मुझे लगता है कि चिड़ियाघर रोलप्ली फ़ंक्शन काम नहीं करेगा। लूप के लिए एक बेवकूफ का उपयोग करने का एक उदाहरण यहां दिया गया है:

library(data.table) 
df <- data.frame(
    id=30000, 
    date=rep(as.IDate(as.IDate("2012-01-01")+0:29, origin="1970-01-01"), each=1000), 
    factor1=rep(1:5, each=200), 
    factor2=1:5, 
    value=rnorm(30, 100, 10) 
) 

dt = data.table(df) 
setkeyv(dt, c("date", "factor1", "factor2")) 

get_window <- function(date, factor1, factor2) { 
    criteria <- data.table(
    date=as.IDate((date - 7):(date - 1), origin="1970-01-01"), 
    factor1=as.integer(factor1), 
    factor2=as.integer(factor2) 
) 
    return(dt[criteria][, value]) 
} 

output <- data.table(unique(dt[, list(date, factor1, factor2)]))[, window_median:=as.numeric(NA)] 

for(i in nrow(output):1) { 
    print(i) 
    output[i, window_median:=median(get_window(date, factor1, factor2))] 
} 
+2

+1, अच्छा सवाल। – Ryogi

+0

+1 भी। क्या आप डेटा आकार और समय के बारे में अधिक जानकारी प्रदान कर सकते हैं। एलन के उत्तर से आपकी टिप्पणी से (एलन और एलन अलग-अलग लोग हैं?), इसमें 6.4s (बनाम 973s 'data.frame' के लिए) लेते हैं और आप 6.4 और आगे सुधारना चाहते हैं? –

+0

एलन और एलन अलग-अलग लोग हैं :)। डेटासेट में ~ 650,000 पंक्तियां हैं। मैं ऐसे समाधान के साथ आया जो बहुत तेजी से काम करता है लेकिन बहुत यादगार गहन है। इस पर कोई विचार कैसे आगे बढ़ाया जा सकता है? – alan

उत्तर

6

data.table में वर्तमान में रोलिंग विंडो के लिए कोई विशेष विशेषताएं नहीं हैं। मेरा उत्तर में यहाँ अधिक विस्तार एक और इसी तरह प्रश्न यहाँ करने के लिए:

Is there a fast way to run a rolling regression inside data.table?

रोलिंग मंझला दिलचस्प है। यह एक विशेष समारोह की आवश्यकता होगी कुशलता से (पहले टिप्पणी में के रूप में ही लिंक) करने के लिए: यहाँ

Rolling median algorithm in C

प्रश्न में data.table समाधान और जवाब सब बहुत अक्षम, एक उचित विशेष rollingmedian समारोह के सापेक्ष हैं (जो आर afaik के लिए उपलब्ध नहीं है)।

+6

क्या हम FR # 2185 की प्राथमिकता बढ़ा सकते हैं? "विंडोज़ स्लाइडिंग के लिए विशेषताएं/दस्तावेज जोड़ें"। मेरे परिप्रेक्ष्य से इसे किसी भी रोल योग, माध्य इत्यादि की आवश्यकता नहीं है यह बेहतर है कि फ्रेमवर्क फ़ंक्शन "रोलफुन =" या नीचे दी गई विधियों के लिए बेहतर है: मैंने पहले से ही रोल के साथ स्वयं जुड़ने की कोशिश की है = 30, बहु = 'सब', allow.cartesian सफलता के बिना इसे प्राप्त करने के लिए। इसके अलावा "एन" वेक्टर को स्वीकार करने के लिए अच्छा होगा, न केवल स्केलर। – jangorecki

+6

@MusX ठीक है मैंने शीर्ष पर प्राथमिकता बढ़ा दी है। –

0

यह समाधान काम करता है लेकिन इसमें कुछ समय लगता है।

df <- data.frame(
    id=30000, 
    date=rep(seq.Date(from=as.Date("2012-01-01"),to=as.Date("2012-01-30"),by="d"),each=1000), 
    factor1=rep(1:5, each=200), 
    factor2=1:5, 
    value=rnorm(30, 100, 10) 
) 

myFun <- function(dff,df){ 
    median(df$value[df$date>as.Date(dff[2])-8 & df$date<as.Date(dff[2])-1 & df$factor1==dff[3] & df$factor2==dff[4]]) 
} 

week_Med <- apply(df,1,myFun,df=df) 

week_Med_df <- cbind(df,week_Med) 
+0

धन्यवाद! ऐसा लगता है कि हालांकि लूप के लिए लंबा समय लगता है। सिस्टम से प्राप्त होने वाले समय लूप के लिए आपके कोड 6.4s के लिए 973 हैं। मुझे लगता है कि अंतर डेटाटेबल पैकेज का उपयोग होना चाहिए – alan

3

मैं एक लेटे हुए डेटासेट बनाकर और एक बड़ी भागीदारी करके 1.4s तक उदाहरण प्राप्त करने में कामयाब रहा।

df <- data.frame(
    id=30000, 
    date=rep(as.IDate(as.IDate("2012-01-01")+0:29, origin="1970-01-01"), each=1000), 
    factor1=rep(1:5, each=200), 
    factor2=1:5, 
    value=rnorm(30, 100, 10) 
) 

dt2 <- data.table(df) 
setkeyv(dt, c("date", "factor1", "factor2")) 

unique_set <- data.table(unique(dt[, list(original_date=date, factor1, factor2)])) 
output2 <- data.table() 
for(i in 1:7) { 
    output2 <- rbind(output2, unique_set[, date:=original_date-i]) 
}  

setkeyv(output2, c("date", "factor1", "factor2")) 
output2 <- output2[dt] 
output2 <- output2[, median(value), by=c("original_date", "factor1", "factor2")] 

यह परीक्षण डेटासेट पर बहुत अच्छी तरह से काम करता है लेकिन मेरे असली पर यह 8 जीबी रैम के साथ विफल रहता है। मैं इसे काम करने के लिए हाई मेमोरी ईसी 2 इंस्टेंस (17, 34 या 68 जीबी रैम के साथ) में जाने की कोशिश करने जा रहा हूं। कम मेमोरी गहन तरीके से इसे कैसे करें इस पर कोई विचार

+0

बस पहली नज़र में, 'for' के अंदर 'rbind' बहुत अधिक रैम का उपयोग करेगा। उस बिट को करने का एक और सीधा तरीका होना चाहिए। –

+0

[यह प्रश्न] (http://stackoverflow.com/questions/1309263/rolling-median-algorithm-in-c) मध्यस्थ रोलिंग के लिए बाइनरी खोज, आर और सी का उल्लेख करता है। आगे की जांच करने के लिए आपके लिए वादा करता है; यानी, _algorithm_ के बारे में सोचें। –