एक सामान्य समय श्रृंखला की अवधि का पता लगाना


53

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

unsigned int discover_period(vector<double> v);

vनमूने युक्त सरणी कहां है, और वापसी मान संकेत की अवधि है। मुख्य बिंदु यह है कि, फिर से, मैं विश्लेषण किए गए संकेत के बारे में कोई धारणा नहीं बना सकता। मैंने पहले से ही सिग्नल ऑटोकैरेलेशन (एक कोर्रोग्राम की चोटियों का पता लगाने) के आधार पर एक दृष्टिकोण की कोशिश की, लेकिन यह उतना मजबूत नहीं है जितना मैं चाहूंगा।


1
क्या आपने xts की कोशिश की :: आवधिकता?
फेब्रीको 3

जवाबों:


49

यदि आपको वास्तव में पता नहीं है कि आवधिकता क्या है, तो संभवतः सबसे अच्छा दृष्टिकोण वर्णक्रमीय घनत्व के अधिकतम के अनुरूप आवृत्ति को खोजना है। हालांकि, कम आवृत्तियों पर स्पेक्ट्रम प्रवृत्ति से प्रभावित होगा, इसलिए आपको पहले श्रृंखला को बंद करने की आवश्यकता है। निम्नलिखित आर फ़ंक्शन को अधिकांश श्रृंखला के लिए काम करना चाहिए। यह एकदम सही है, लेकिन मैंने इसे कुछ दर्जन उदाहरणों पर परीक्षण किया है और यह ठीक काम करने लगता है। यह 1 डेटा के लिए वापस आ जाएगा जिसमें कोई मजबूत आवधिकता नहीं है, और अवधि की लंबाई अन्यथा।

अद्यतन: फ़ंक्शन का संस्करण 2। यह बहुत तेज है और अधिक मजबूत प्रतीत होता है।

find.freq <- function(x)
{
    n <- length(x)
    spec <- spec.ar(c(x),plot=FALSE)
    if(max(spec$spec)>10) # Arbitrary threshold chosen by trial and error.
    {
        period <- round(1/spec$freq[which.max(spec$spec)])
        if(period==Inf) # Find next local maximum
        {
            j <- which(diff(spec$spec)>0)
            if(length(j)>0)
            {
                nextmax <- j[1] + which.max(spec$spec[j[1]:500])
                period <- round(1/spec$freq[nextmax])
            }
            else
                period <- 1
        }
    }
    else
        period <- 1
    return(period)
}

धन्यवाद। फिर से, मैं जल्द से जल्द इस दृष्टिकोण की कोशिश करूंगा और यहां अंतिम परिणाम लिखूंगा।
गियानलूका

2
आपका विचार काफी अच्छा है, लेकिन मेरे मामले में, यह dl.dropbox.com/u/540394/chart.png जैसी वास्तव में सरल (और इतना शोर नहीं) समय की अवधि का पता लगाने में विफल रहता है । मेरे "अनुभवजन्य" दृष्टिकोण (ऑटोकार्ट्रेशन पर आधारित) के साथ, मैंने जो सरल एल्गोरिथ्म लिखा है, वह 1008 की सटीक अवधि देता है (प्रत्येक 10 मिनट में एक नमूना होता है, इसका मतलब है 1008/24/6 = 7, इसलिए साप्ताहिक आवधिकता)। मेरी मुख्य समस्याएं हैं: 1) यह अभिसरण करने के लिए बहुत धीमा है (इसके लिए बहुत अधिक ऐतिहासिक डेटा की आवश्यकता है) और मुझे प्रतिक्रियाशील, ऑनलाइन दृष्टिकोण की आवश्यकता है; 2) यह एक स्मृति उपयोग बिंदु से नरक के रूप में अक्षम है; 3) यह बिल्कुल मजबूत नहीं है;
gianluca

धन्यवाद। दुर्भाग्य से, यह अभी भी काम नहीं करेगा जैसा कि मैं उम्मीद करूंगा। पिछली टिप्पणी की एक ही समय श्रृंखला के लिए यह १६६ रिटर्न देता है, जो केवल आंशिक रूप से सही है (मेरे दृष्टिकोण से, स्पष्ट साप्ताहिक अवधि अधिक दिलचस्प है)। और एक बहुत शोर समय श्रृंखला का उपयोग करते हुए, यह एक dl.dropbox.com/u/540394/chart2.png (एक टीसीपी रिसीवर विंडो विश्लेषण) की तरह, फ़ंक्शन 10 देता है, जबकि मैं 1 की उम्मीद करता हूं (मैं कोई स्पष्ट नहीं देख सकता हूं अवधि)। BTW मुझे पता है कि यह वास्तव में मुश्किल है कि मैं क्या ढूंढ रहा हूं, क्योंकि मैं बहुत अलग संकेतों के साथ काम कर रहा हूं।
gianluca

166 एक खराब अनुमान नहीं है 168. यदि आप जानते हैं कि डेटा एक साप्ताहिक पैटर्न के साथ प्रति घंटा मनाया जाता है, तो आवृत्ति का अनुमान क्यों लगाया जाए?
रोब हंडमैन

5
एक उन्नत संस्करण पूर्वानुमान पैकेज में हैfindfrequency
रोब हंडमैन

10

यदि आप इस प्रक्रिया को स्थिर होने की उम्मीद करते हैं - समय के साथ आवधिकता / मौसमी परिवर्तन नहीं होगा - तो ची-स्क्वायर पीरियोग्राम (उदाहरण के लिए सोकोलोव और बसहेल, 1978) जैसा कुछ अच्छा विकल्प हो सकता है। यह आमतौर पर सर्कैडियन डेटा के विश्लेषण में उपयोग किया जाता है, जिसमें बहुत बड़ी मात्रा में शोर हो सकता है, लेकिन बहुत स्थिर आवधिकता होने की उम्मीद है।

यह दृष्टिकोण तरंग के आकार के बारे में कोई धारणा नहीं बनाता है (इसके अलावा यह चक्र से चक्र के अनुरूप है), लेकिन इसके लिए आवश्यक है कि कोई भी शोर निरंतर मतलब का हो और सिग्नल से असंबद्ध हो।

chisq.pd <- function(x, min.period, max.period, alpha) {
N <- length(x)
variances = NULL
periods = seq(min.period, max.period)
rowlist = NULL
for(lc in periods){
    ncol = lc
    nrow = floor(N/ncol)
    rowlist = c(rowlist, nrow)
    x.trunc = x[1:(ncol*nrow)]
    x.reshape = t(array(x.trunc, c(ncol, nrow)))
    variances = c(variances, var(colMeans(x.reshape)))
}
Qp = (rowlist * periods * variances) / var(x)
df = periods - 1
pvals = 1-pchisq(Qp, df)
pass.periods = periods[pvals<alpha]
pass.pvals = pvals[pvals<alpha]
#return(cbind(pass.periods, pass.pvals))
return(cbind(periods[pvals==min(pvals)], pvals[pvals==min(pvals)]))
}

x = cos( (2*pi/37) * (1:1000))+rnorm(1000)
chisq.pd(x, 2, 72, .05)

अंतिम दो पंक्तियाँ केवल एक उदाहरण हैं, जिससे पता चलता है कि यह एक शुद्ध त्रिकोणमितीय फ़ंक्शन की अवधि की पहचान कर सकता है, यहां तक ​​कि बहुत सारे योजक शोर भी।

जैसा कि लिखा गया है, alphaकॉल में अंतिम तर्क ( ) शानदार है, फ़ंक्शन केवल 'सर्वश्रेष्ठ' अवधि देता है जो इसे मिल सकता है; पहले returnकथन को अनसुना कर दें और दूसरे पर टिप्पणी करें कि यह स्तर पर महत्वपूर्ण सभी अवधियों की सूची लौटाएगा alpha

यह फ़ंक्शन यह सुनिश्चित करने के लिए किसी भी प्रकार की पवित्रता की जाँच नहीं करता है कि आपने पहचानने योग्य अवधि में डाल दिया है, और न ही यह (यह कर सकता है) आंशिक अवधि के साथ काम करता है, और न ही यदि आप निर्णय लेते हैं, तो इसमें किसी भी प्रकार का कई तुलनात्मक नियंत्रण नहीं है। कई अवधियों में देखें। लेकिन इसके अलावा यह काफी मजबूत होना चाहिए।


दिलचस्प लगता है, लेकिन मुझे आउटपुट समझ में नहीं आता है, यह मुझे नहीं बताता कि यह अवधि कहाँ से शुरू होती है, और 1. का सबसे अधिक अंतराल
हरमन टूथ्रोट

3

आप परिभाषित करना चाह सकते हैं कि आप और अधिक स्पष्ट रूप से (अपने आप को, यदि यहाँ नहीं हैं) चाहते हैं। यदि आप जिस चीज़ की तलाश कर रहे हैं वह आपके शोर डेटा में निहित सबसे महत्वपूर्ण स्थिर स्थिर अवधि है, तो लेने के लिए अनिवार्य रूप से दो मार्ग हैं:

1) एक मजबूत आटोक्लेररेशन अनुमान की गणना करें, और अधिकतम गुणांक
2 लें) एक मजबूत पावर वर्णक्रमीय घनत्व अनुमान की गणना करें, और अधिकतम स्पेक्ट्रम लें

# 2 के साथ समस्या यह है कि किसी भी शोर समय श्रृंखला के लिए, आपको कम आवृत्तियों में बड़ी मात्रा में बिजली मिलेगी, जिससे अंतर करना मुश्किल हो जाएगा। इस समस्या को हल करने के लिए कुछ तकनीकें हैं (यानी पूर्व-श्वेत, फिर पीएसडी का अनुमान लगाएं), लेकिन अगर आपके डेटा से सही अवधि काफी लंबी है, तो स्वत: पता लगाना iffy होगा।

आपकी सबसे अच्छी शर्त संभवतः एक मजबूत ऑटोक्रॉलेशन रूटीन को लागू करना है जैसे कि अध्याय 8.6, 8.7 में रोबस्ट स्टैटिस्टिक्स - थ्योरी एंड मेथड्स बाय मैरोना, मार्टिन और योहाई में पाया जा सकता है । Google को "मजबूत डर्बिन-लेविंसन" के लिए खोज करने से कुछ परिणाम भी मिलेंगे।

यदि आप केवल एक सरल उत्तर की तलाश में हैं, तो मुझे यकीन नहीं है कि कोई मौजूद है। समय श्रृंखला में अवधि का पता लगाना जटिल हो सकता है, और एक स्वचालित दिनचर्या के लिए पूछना जो जादू कर सकता है बहुत अधिक हो सकता है।


आपके बहुमूल्य सुझाव के लिए धन्यवाद, मैं उस पुस्तक को अवश्य देखूंगा।
जियानलुका

3

आप अपने डेटा की तात्कालिक आवृत्ति को मापने के लिए DSP सिद्धांत से हिल्बर्ट परिवर्तन का उपयोग कर सकते हैं। साइट http://ta-lib.org/ में वित्तीय डेटा के प्रमुख चक्र अवधि को मापने के लिए खुला स्रोत कोड है; प्रासंगिक फ़ंक्शन को HT_DCPERIOD कहा जाता है; आप इसका उपयोग करने में सक्षम हो सकते हैं या अपने उद्देश्यों के लिए कोड को अनुकूलित कर सकते हैं।


3

एक अलग दृष्टिकोण Empirical Mode Decomposition हो सकता है। R पैकेज को विधि के आविष्कारक द्वारा विकसित EMD कहा जाता है :

require(EMD)
ndata <- 3000  
tt2 <- seq(0, 9, length = ndata)  
xt2 <- sin(pi * tt2) + sin(2* pi * tt2) + sin(6 * pi * tt2) + 0.5 * tt2  
try <- emd(xt2, tt2, boundary = "wave")  
### Ploting the IMF's  
par(mfrow = c(try$nimf + 1, 1), mar=c(2,1,2,1))  
rangeimf <- range(try$imf)  
for(i in 1:try$nimf) {  
plot(tt2, try$imf[,i], type="l", xlab="", ylab="", ylim=rangeimf, main=paste(i, "-th IMF", sep="")); abline(h=0)  
}  
plot(tt2, try$residue, xlab="", ylab="", main="residue", type="l", axes=FALSE); box()

विधि को एक अच्छे कारण के लिए 'एम्पिरिकल' ब्रांड किया गया था और एक जोखिम है कि आंतरिक मोड फ़ंक्शंस (व्यक्तिगत एडिटिव घटक) मिश्रित हो जाते हैं। दूसरी ओर विधि बहुत सहज है और चक्रीयता के त्वरित दृश्य निरीक्षण के लिए सहायक हो सकती है।


0

रोब हंडमैन के पोस्ट के संदर्भ में https://stats.stackexchange.com/a/1214/70282 से ऊपर

Find.freq फ़ंक्शन शानदार ढंग से काम करता है। मेरे द्वारा उपयोग किए जा रहे दैनिक डेटा सेट पर, यह 7 होने की आवृत्ति को सही ढंग से काम करता है।

जब मैंने इसे केवल सप्ताह के दिनों में आज़माया, तो यह बताया कि आवृत्ति 23 है, जो उल्लेखनीय रूप से 21.42857 = 29.6 * 5/7 के करीब है जो एक महीने में कार्य दिवसों की औसत संख्या है। (या इसके विपरीत 23 * 7/5 32 है।)

अपने दैनिक डेटा को देखते हुए, मैंने पहली अवधि लेने की एक कूबड़ के साथ प्रयोग किया, इसके द्वारा औसत और फिर अगली अवधि ढूंढना, आदि नीचे देखें:

find.freq.all = समारोह (एक्स) {  
  च = find.freq (x);
  freqs = c (च);  
  जबकि (च> 1) {
    = 1 शुरू; #also try start = f;
    एक्स = period.apply (एक्स, seq (शुरू, लंबाई (एक्स), च), इसका मतलब यह); 
    च = find.freq (x);
    freqs = c (freqs, च);
  }
  if (लंबाई (freqs) == 1) {return (freqs); }
  के लिए (मैं 2 में: लंबाई (freqs)) {
    freqs [i] = freqs [i] * freqs [i-1];
  }
  freqs [1: (लंबाई (freqs) -1)];
}
find.freq.all (dailyts) # मनोरंजक दैनिक डेटा

उपरोक्त (7,28) या (7,35) इस बात पर निर्भर करता है कि seq 1 या f से शुरू होता है। (ऊपर टिप्पणी देखें।)

जिसका अर्थ यह होगा कि msts (...) के लिए मौसमी अवधि (7,28) या (7,35) होनी चाहिए।

एल्गोरिथम मापदंडों की संवेदनशीलता को देखते हुए तर्क प्रारंभिक स्थितियों के प्रति संवेदनशील दिखाई देता है। 28 और 35 का मतलब 31.5 है जो एक महीने की औसत लंबाई के करीब है।

मुझे संदेह है कि मैंने पहिया को फिर से स्थापित किया, इस एल्गोरिथ्म का नाम क्या है? कहीं आर में बेहतर कार्यान्वयन है?

बाद में, मैंने 7 के माध्यम से 1 की सभी शुरुआतओं में उपरोक्त कोड चलाया और मुझे दूसरी अवधि के लिए 35,35,28,28,28,28,28 मिले। औसत 30 तक काम करता है जो एक महीने में दिनों की औसत संख्या है। दिलचस्प ...

कोई विचार या टिप्पणी?


0

एक भी Ljung- बॉक्स परीक्षण का उपयोग यह पता लगाने के लिए कर सकता है कि कौन सी मौसमी अंतर सबसे अधिक स्थिरता तक पहुंचता है। मैं एक अलग विषय पर काम कर रहा था और मैंने वास्तव में उन्हीं उद्देश्यों के लिए इसका इस्तेमाल किया। मासिक डेटा के लिए अलग-अलग अवधि जैसे 3 से 24 की कोशिश करें। और Ljung-Box द्वारा उनमें से प्रत्येक का परीक्षण करें और ची-स्क्वायर परिणामों को स्टोर करें। और सबसे कम ची-वर्ग मान के साथ अवधि चुनें।

यहाँ ऐसा करने के लिए एक सरल कोड है।

minval0 <- 5000 #assign a big number to be sure Chi values are smaller
minindex0 <- 0
periyot <- 0

for (i in 3:24) { #find optimum period by Qtests over original data

        d0D1 <- diff(a, lag=i)

        #store results
        Qtest_d0D1[[i]] <- Box.test(d0D1, lag=20, type = "Ljung-Box")

        #store Chi-Square statistics
        sira0[i] <- Qtest_d0D1[[i]][1]
}
#turn list to a data frame, then matrix
datam0 <- data.frame(matrix(unlist(sira0), nrow=length(Qtest_d0D1)-2, byrow = T))
datamtrx0 <- as.matrix(datam0[])
#get min value's index
minindex0 <- which(datamtrx0 == min(datamtrx0), arr.ind = F)
periyot <- minindex0 + 2
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.