2009-06-21 15 views
5

एक मेज जहां पहले कॉलम एक निश्चित संदर्भ बिंदु अतीत सेकंड है और दूसरा एक एक मनमाना माप है यह देखते हुए:चौरसाई अनियमित नमूना समय डेटा

6 0.738158581 
21 0.801697222 
39 1.797224596 
49 2.77920469 
54 2.839757536 
79 3.832232283 
91 4.676794376 
97 5.18244704 
100 5.521878863 
118 6.316630137 
131 6.778507504 
147 7.020395216 
157 7.331607129 
176 7.637492223 
202 7.848079136 
223 7.989456499 
251 8.76853608 
278 9.092367123 
    ... 

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

क्या कोई मेरी मदद कर सकता है?

संपादित रों

  1. मैं प्रत्येक कच्चे पढ़ने के लिए एक सरल पढ़ने, और समतल पढ़ने चाहते कच्चे पढ़ने का समांतर माध्य और पिछले 100 (डेल्टा) सेकंड में किसी भी अन्य हो रहा है । (जॉन, आप सही हैं)

  2. विशाल ~ 1E6 - 10E6 लाइनों + तंग रैम

  3. के साथ काम करने की जरूरत है डेटा लगभग यादृच्छिक की पैदल दूरी पर

  4. डेटा

क्रमबद्ध हो जाता है है

RESOLUTION

मैंने जे माचिन और याएचु द्वारा प्रस्तावित समाधानों का परीक्षण किया है। दोनों ने एक ही परिणाम दिए, हालांकि, मेरे डेटा सेट पर, जे माचिन का संस्करण तेजी से प्रदर्शन करता है, जबकि यैचु की रैखिक है। अनुसरण कर रहे हैं निष्पादन समय के रूप में IPython के % timeit द्वारा मापा (माइक्रोसेकंड में):

data size J Machin yairchu 
10  90.2  55.6 
50   930   258 
100   3080  514 
500   64700  2660 
1000  253000  5390 
2000  952000  11500 

मदद के लिए आप सभी को धन्यवाद।

+1

यह बहुत बड़ा NumPy सरणी में नियंत्रित किया जा करने के लिए है? आपके पास कितने आइटम हैं? –

+0

इस रैखिक प्रक्षेप अंक है कि 100 के गुणज हैं खोजने के लिए है? –

+0

यदि आपके पास चिकनाई की आवश्यकता है, तो कृपया थोड़ा और विस्तृत करें। मैंने दो बार कोशिश की लेकिन मैं आपके इस वर्णन को पार्स नहीं कर सकता: "मुझे प्रत्येक माप से पहले 100 सेकंड तक पढ़ने के औसत से डेटा को सुचारू बनाना होगा"। – rix0rrr

उत्तर

2

मैं एक योग परिणाम उपयोग कर रहा हूँ जो मैं नए सदस्यों को जोड़ने और पुराने लोगों को घटाकर कर रहा हूँ करने के लिए। हालांकि इस तरह से कोई फ़्लोटिंग पॉइंट त्रुटियों को जमा कर सकता है।

इसलिए मैं एक सूची के साथ एक "Deque" को लागू। और जब भी मेरा डेक एक छोटे आकार में reallocates। मैं उसी अवसर पर राशि का पुनर्मूल्यांकन करता हूं।

अप सहित बिंदु एक्स एक्स बात करने के लिए तो वहाँ औसत करने के लिए कम से कम एक नमूना बिंदु मैं भी औसत की गणना कर रहा हूँ।

def getAvgValues(data, avgSampleTime): 
    lastTime = 0 
    prevValsBuf = [] 
    prevValsStart = 0 
    tot = 0 
    for t, v in data: 
    avgStart = t - avgSampleTime 
    # remove too old values 
    while prevValsStart < len(prevValsBuf): 
     pt, pv = prevValsBuf[prevValsStart] 
     if pt > avgStart: 
     break 
     tot -= pv 
     prevValsStart += 1 
    # add new item 
    tot += v 
    prevValsBuf.append((t, v)) 
    # yield result 
    numItems = len(prevValsBuf) - prevValsStart 
    yield (t, tot/numItems) 
    # clean prevVals if it's time 
    if prevValsStart * 2 > len(prevValsBuf): 
     prevValsBuf = prevValsBuf[prevValsStart:] 
     prevValsStart = 0 
     # recalculate tot for not accumulating float precision error 
     tot = sum(v for (t, v) in prevValsBuf) 
+0

(1) यह एक डेक का एक बहुत ही दिलचस्प कार्यान्वयन है। (2) मुझे संदेह है कि ओपी फ़्लोटिंग पॉइंट राउंडिंग त्रुटियों के बारे में बहुत चिंतित है; वे निश्चित रूप से चिकनाई के गंभीर परिवर्तनों की तुलना में बहुत छोटे कटौती करेंगे ... लेकिन यदि वह है, तो चलने वाले कुल को बनाए रखने के लिए एक कहान योजक का उपयोग किया जा सकता है। –

+0

ध्यान दें कि यह एक घातीय चलती औसत (http://stackoverflow.com/questions/1023860/exponential-moving-Average-sampled-at-varying-times/1024008) की तुलना में बहुत संगणकीय रूप से गहन है। जब तक आपको विशेष रूप से यह सुनिश्चित करने की आवश्यकता न हो कि समय के भीतर सभी नमूने समान रूप से योगदान दें, और पुराने लोग योगदान नहीं देते हैं, तो मैं अधिक कुशल ईएमए के साथ जाऊंगा। –

+0

@ कर्ट सैम्पसन: ओपी ने विशेष रूप से इस – yairchu

-1

इस तरह के बारे में कुछ, आखिरी बार समय अंतर के साथ मूल्यों को संग्रहित रखें> 100, औसत और उपज ऐसे मूल्य उदा।

def getAvgValues(data): 
    lastTime = 0 
    prevValues = [] 
    avgSampleTime=100 

    for t, v in data: 
     if t - lastTime < avgSampleTime: 
      prevValues.append(v) 
     else: 
      avgV = sum(prevValues)/len(prevValues) 
      lastTime = t 
      prevValues = [v] 
      yield (t,avgV) 

for v in getAvgValues(data): 
    print v 
+0

उन्होंने मूल माप के हर समय के लिए पिछले 100 सेकंड के औसत के लिए कहा। आप अपने उदाहरण – yairchu

+0

हम्म के लिए केवल 2 परिणाम देते हैं, मैंने इसे गलत समझा, किसी भी तरह से ऐसा लगता है कि आपने सही समाधान –

+0

के लिए इसे संशोधित किया है, मैंने इसे वास्तव में संशोधित नहीं किया है। मैंने अभी आपके परिवर्तनीय नामों का उपयोग किया है। – yairchu

2

आपने आउटपुट को ठीक से नहीं कहा है। मुझे लगता है कि आप प्रत्येक कच्चे पढ़ने के लिए एक चिकना पढ़ना चाहते हैं, और चिकना पढ़ना कच्चे पढ़ने और पिछले 100 (डेल्टा) सेकंड में किसी भी अन्य के अंकगणितीय अर्थ होना है।

संक्षिप्त उत्तर: संग्रह.deque का उपयोग करें ... यह कभी भी रीडिंग के "डेल्टा" सेकंड से अधिक नहीं रखेगा। जिस तरह से मैंने इसे सेट अप किया है, आप डेक को एक सूची की तरह ही इलाज कर सकते हैं, और आसानी से मतलब या कुछ फैंसी गिज्मोइड की गणना कर सकते हैं जो हालिया रीडिंग्स को अधिक भार देता है।

लांग जवाब:

>>> the_data = [tuple(map(float, x.split())) for x in """\ 
... 6  0.738158581 
... 21  0.801697222 
[snip] 
... 251  8.76853608 
... 278  9.092367123""".splitlines()] 
>>> import collections 
>>> delta = 100.0 
>>> q = collections.deque() 
>>> for t, v in the_data: 
...  while q and q[0][0] <= t - delta: 
...   # jettison outdated readings 
...   _unused = q.popleft() 
...  q.append((t, v)) 
...  count = len(q) 
...  print t, sum(item[1] for item in q)/count, count 
... 
... 
6.0 0.738158581 1 
21.0 0.7699279015 2 
39.0 1.112360133 3 
49.0 1.52907127225 4 
54.0 1.791208525 5 
79.0 2.13137915133 6 
91.0 2.49500989771 7 
97.0 2.8309395405 8 
100.0 3.12993279856 9 
118.0 3.74976297144 9 
131.0 4.41385300278 9 
147.0 4.99420529389 9 
157.0 5.8325615685 8 
176.0 6.033109419 9 
202.0 7.15545189083 6 
223.0 7.4342562845 6 
251.0 7.9150342134 5 
278.0 8.4246097095 4 
>>> 

संपादित

वन-स्टॉप शॉप: अपनी कल्पना यहाँ gizmoid मिलता है।कोड यह रहा:

numerator = sum(item[1] * upsilon ** (t - item[0]) for item in q) 
denominator = sum(upsilon ** (t - item[0]) for item in q) 
gizmoid = numerator/denominator 

जहां upsilon, बस ऊपर शून्य थोड़ा समरेखण करता है, एक आप समांतर माध्य से अधिक बर्बाद CPU समय है, और एक से अधिक देता हो जाता है एक छोटे से कम से कम 1.0 (< = शून्य गैर कानूनी है होना चाहिए आपके उद्देश्य के विपरीत)।

+0

ऐसा लगता है कि एक नियमित सूची यहां .pople (0) के बजाय .pop (0) का उपयोग करके काम करेगी। Collections.deque का क्या फायदा है? – Paul

+2

पायथन सूची के बाईं ओर पॉपिंग ओ (एन) है; एक डेक के बाईं ओर पॉपिंग ओ (1) –

0

आपका डाटा मोटे तौर पर रैखिक हो रहा है:

Plot of your data http://rix0r.nl/~rix0r/share/shot-20090621.144851.gif

समरेखण किस तरह आप के लिए देख रहे हैं? कम से कम वर्ग इस डेटा सेट के लिए एक लाइन के फिट फिट? कुछ प्रकार के कम-पास फ़िल्टर? या कुछ और?

कृपया हमें बताएं ताकि हम आप थोड़ा बेहतर सलाह दे सकते हैं आवेदन बताओ।

संपादित करें: उदाहरण के लिए, आवेदन के आधार पर, पहले और अंतिम बिंदु के बीच एक रेखा को अलग करना आपके उद्देश्यों के लिए पर्याप्त हो सकता है।

+0

इस बार यह रैखिक हो सकता है। – Nosredna

0

यह एक यह रेखीय बनाता है: जैसे आप एक सरल राउंडिंग सूत्र की जरूरत

def process_data(datafile): 
    previous_n = 0 
    previous_t = 0 
    for line in datafile: 
     t, number = line.strip().split() 
     t = int(t) 
     number = float(number) 
     delta_n = number - previous_n 
     delta_t = t - previous_t 
     n_per_t = delta_n/delta_t 
     for t0 in xrange(delta_t): 
      yield previous_t + t0, previous_n + (n_per_t * t0) 
     previous_n = n 
     previous_t = t 

f = open('datafile.dat') 

for sample in process_data(f): 
    print sample 
+0

(1) के लिए पूछा। Thestrip() अनावश्यक है। (2) आप पिछली बार * हर बार अद्यतन करने के लिए भूल गए हैं (3) फिर भी, यह स्पष्ट नहीं है कि यह क्या करना है ... यह पिछले पढ़ने और वर्तमान पढ़ने के बीच एक रैखिक इंटरपोलेशन करने के लिए प्रतीत होता है, एक दूसरे अंतराल पर - ओपी की आवश्यकताओं की एक दिलचस्प व्याख्या। (3) मुझे लगता है कि आप 'xrange (1, delta_t + 1) ' –

-2

लग रहा है। एक मनमाना अंतराल के किसी भी संख्या के दौर के लिए:

दौर (संख्या/अंतराल) * अंतराल

आप "के लिए अग्रणी करने के लिए" या "के बाद से" को प्रभावित करता है के लिए फर्श या छत के साथ दौर स्थानापन्न कर सकते हैं। यह एसक्यूएल सहित किसी भी भाषा में काम कर सकता है।

0

ओ (1) स्मृति यदि आप एक से अधिक बार इनपुट को पुन: सक्रिय कर सकते हैं - तो आप "बाएं" और "दाएं" के लिए एक इटरेटर का उपयोग कर सकते हैं।

def getAvgValues(makeIter, avgSampleTime): 
    leftIter = makeIter() 
    leftT, leftV = leftIter.next() 
    tot = 0 
    count = 0 
    for rightT, rightV in makeIter(): 
    tot += rightV 
    count += 1 
    while leftT <= rightT - avgSampleTime: 
     tot -= leftV 
     count -= 1 
     leftT, leftV = leftIter.next() 
    yield rightT, tot/count 
+1

में टी 0 के लिए मतलब है कि मुझे लगता है कि ओपी वास्तविक समय में चिकना मूल्य प्रदर्शित करना चाहता है ... गहन देखभाल वार्ड में दिल-धड़कन मॉनिटर सोचें। –

0

जबकि यह एक तेजी से खस्ताहाल औसत है, बजाय एक कुल औसत देता है, मुझे लगता है कि आप मैं एक exponential moving average with varying alpha क्या कहा जाता है, जो वास्तव में एक एकल पोल कम पास फिल्टर है सकते हैं। अब उस प्रश्न का समाधान है, और यह डेटा बिंदुओं की संख्या के लिए समय रैखिक में चलता है। देखें कि यह आपके लिए काम करता है या नहीं।

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