2012-07-05 9 views
34

Znowu gram w Pythonie i znalazłem zgrabną książkę z przykładami. Jednym z przykładów jest wykreślenie niektórych danych. Mam plik .txt z dwiema kolumnami i mam dane. I wykreślić dane w porządku, ale w wykonywaniu mówi: Modyfikacja programu dodatkowo obliczyć i wykreślić z systemem średnio danych, określonych przez:Znaleźć średnią kroczącą z punktów danych w Pythonie

$Y_k=\frac{1}{2r}\sum_{m=-r}^r y_{k+m}$ 

gdzie r=5 w tym przypadku (i y_k jest druga kolumna w pliku danych). Niech program wypisze zarówno oryginalne dane, jak i średnią bieżącą na tym samym wykresie.

Do tej pory mam to:

from pylab import plot, ylim, xlim, show, xlabel, ylabel 
from numpy import linspace, loadtxt 

data = loadtxt("sunspots.txt", float) 
r=5.0 

x = data[:,0] 
y = data[:,1] 

plot(x,y) 
xlim(0,1000) 
xlabel("Months since Jan 1749.") 
ylabel("No. of Sun spots") 
show() 

Więc jak mam obliczyć sumę? W Mathematica jest to proste, ponieważ jest to symboliczna manipulacja (na przykład Sum [i, {i, 0, 10}), ale jak obliczyć sumę w pythonie, która pobiera co dziesięć punktów w danych i uśrednia ją, i robi to do końca punktów?

spojrzałem na książki, ale nic nie znalazł, który by to wyjaśnić: \


heltonbiker kodzie wystarczyły ^^: D

from __future__ import division 
from pylab import plot, ylim, xlim, show, xlabel, ylabel, grid 
from numpy import linspace, loadtxt, ones, convolve 
import numpy as numpy 

data = loadtxt("sunspots.txt", float) 

def movingaverage(interval, window_size): 
    window= numpy.ones(int(window_size))/float(window_size) 
    return numpy.convolve(interval, window, 'same') 

x = data[:,0] 
y = data[:,1] 


plot(x,y,"k.") 
y_av = movingaverage(y, 10) 
plot(x, y_av,"r") 
xlim(0,1000) 
xlabel("Months since Jan 1749.") 
ylabel("No. of Sun spots") 
grid(True) 
show() 

I mam to:

image

Dziękuję bardzo ^^ :)

+1

To dziwne. Ponieważ nie mamy twojego pliku txt, nie można go tutaj przetestować, ale myślę, że nie należy używać linii 'xlim' (na wszelki wypadek). – heltonbiker

+0

Dostałem punkty stąd: http: // www-personal. umich.edu/~mejn/computational-physics/sunspots.dat Usunięcie xlim nie pomogło: \ –

+2

Popełniłem błąd w kodzie! musisz wykonać średnią z tablicy y, a nie x: 'y_av = movingaverage (y, r)' 'plot (x, y_av)'. I możesz użyć Xlim ponownie, jak sądzę. – heltonbiker

Odpowiedz

68

Before reading this answer, bear in mind that there is another answer below, from Roman Kh, which uses numpy.cumsum and is MUCH MUCH FASTER than this one.


Najlepszy Jednym z popularnych sposobów jest zastosowanie ruchomych/średniej ruchomej (albo jakiejkolwiek innej funkcji przesuwne okno) w sygnał jest za pomocą numpy.convolve().

def movingaverage(interval, window_size): 
    window = numpy.ones(int(window_size))/float(window_size) 
    return numpy.convolve(interval, window, 'same') 

Tutaj przerwa to tablica x i window_size jest liczba próbek do rozważenia. Okno będzie wyśrodkowane na każdej próbce, więc pobiera próbki przed i po bieżącej próbce, aby obliczyć średnią. Twój kod stanie się:

plot(x,y) 
xlim(0,1000) 

x_av = movingaverage(interval, r) 
plot(x_av, y) 

xlabel("Months since Jan 1749.") 
ylabel("No. of Sun spots") 
show() 

Mam nadzieję, że to pomoże!

+0

Tutaj pojawia się błąd: Traceback (ostatnie ostatnie połączenie): Plik "C:/Users/*****/Desktop/sunspots_plot.py", wiersz 18, w x_av = moveaverage (x, 5) Plik "C:/Users/*****/Desktop/sunspots_plot.py", wiersz 8, w przenoszeniu danych window = numpy.ones (int (window_size))/float (window_size) NameError: globalna nazwa "numpy" nie jest zdefiniowana –

+2

To znaczy, że nie importowałeś numpy. W rzeczywistości zaimportowano z niego tylko niektóre funkcje: 'linspace' i' loadtxt'. Do tego powinieneś dodać 'ones' i' convolve' o) – heltonbiker

+0

Edytowałem mój kod, a teraz mam obraz, ale średnia jest tylko na ostatniej części wykresu, czy powinienem ręcznie zmienić interwał, aby to posortować? –

0

myślę coś takiego:

aves = [sum(data[i:i+6]) for i in range(0, len(data), 5)] 

Ale zawsze trzeba dokładnie sprawdzić indeksy robią to, czego oczekuję. Zakres chcesz to (0, 5, 10, ...) i dane [0: 6] daje danych [0] ... danych [5]

ETA: oops, a raczej chcesz ave niż suma, oczywiście. Więc faktycznie przy użyciu kodu i wzór:

r = 5 
x = data[:,0] 
y1 = data[:,1] 
y2 = [ave(y1[i-r:i+r]) for i in range(r, len(y1), 2*r)] 
y = [y1, y2] 
+0

Z tym otrzymuję garść tablic, a otrzymuję błędy, gdy próbuję je wykreślić: \ –

+0

Niestety, nie poprawiono literówki, powinno być y1 [ir: i + r] zamiast danych – dreadsci

+0

I tak, y1 ma len (y1) punktów i y2 ma len (y1)/2r wskazuje więc ... chcesz dodać je osobno do wykresu. Idź z rozwiązaniami convolve! – dreadsci

4
ravgs = [sum(data[i:i+5])/5. for i in range(len(data)-4)] 

To nie jest najbardziej efektywnym podejściem, ale to daje odpowiedź i jestem niejasne, czy okno jest 5 punktów lub 10. Jeśli jej 10 wymienić każdy 5 z 10 i 4 z 9

22

Średnia ruchoma to splot, a numpy będzie szybszy niż większość czystych operacji Pythona. Da ci to 10-punktową średnią ruchomą.

import numpy as np 
smoothed = np.convolve(data, np.ones(10)/10) 

Chciałbym również silnie sugerować przy użyciu pakietu pandy wielkie, jeśli pracujesz z danymi timeseries. Jest kilka fajnych moving average operations built in.

+0

Pojawia się błąd: Traceback (ostatnie ostatnie połączenie): Plik " C:/Users/*****/Desktop/sunspots_plot.py ", wiersz 7, w wygładzony = np.convolve (dane, np.ones (10)/(10)) Plik" C: \ Python26 \ lib \ site-packages \ numpy \ core \ numeric.py ", wiersz 787, w convolve return multiarray.correlate (a, v [:: - 1], mode) ValueError: obiekt zbyt głęboki dla pożądanej tablicy –

+0

Thats b/c dane w twoim przypadku są tablicami o wielu wymiarach i powinieneś przechodzić przez tablicę jednowymiarową. W twoim przypadku byłoby wygładzone = np.convolve (y, np.ones/10) – reptilicus

+0

+10 do sugestii "użyj pandy". Nie jest to idealne rozwiązanie dla każdego przypadku, ale prawdopodobnie pozwala zaoszczędzić tylu bólów głowy w przypadku kogoś, kto czyta ten post. – Owen

4

Wystąpił problem z zaakceptowaną odpowiedzią. Myślę, że musimy użyć "prawidłowego" zamiast "tego samego" tutaj - return numpy.convolve(interval, window, 'same').

jako przykład wypróbować IZ tym zbiór danych = [1,5,7,2,6,7,8,2,2,7,8,3,7,3,7,3,15,6] - wynik powinien być [4.2,5.4,6.0,5.0,5.0,5.2,5.4,4.4,5.4,5.6,5.6,4.6,7.0,6.8], ale o „same” daje nam nieprawidłowe wyjście [2.6,3.0,4.2,5.4,6.0,5.0,5.0,5.2,5.4,4.4,5.4,5.6,5.6, 4.6,7.0,6.8,6.2,4.8]

kodu Rusty aby to wypróbować -:

result=[] 
dataset=[1,5,7,2,6,7,8,2,2,7,8,3,7,3,7,3,15,6] 
window_size=5 
for index in xrange(len(dataset)): 
    if index <=len(dataset)-window_size : 
     tmp=(dataset[index]+ dataset[index+1]+ dataset[index+2]+ dataset[index+3]+ dataset[index+4])/5.0 
     result.append(tmp) 
    else: 
     pass 

result==movingaverage(y, window_size) 

Wypróbuj to z ważnym & sam i sprawdź, czy matematyka ma sens.

Patrz też -: http://sentdex.com/sentiment-analysisbig-data-and-python-tutorials-algorithmic-trading/how-to-chart-stocks-and-forex-doing-your-own-financial-charting/calculate-simple-moving-average-sma-python/

+0

Nie wypróbowałem tego, ale przyjrzę się temu od dłuższego czasu, odkąd zakodowałem w Pythonie. –

+0

@dingo_d Dlaczego szybko nie wypróbujesz tego z zardzewiałym kodem (i przykładowym zbiorem danych (jako prostą listą), napisałem? Dla niektórych leniwych ludzi (jak byłem na początku) - jego maski Fakt, że średnia krocząca jest niepoprawna. Prawdopodobnie powinieneś rozważyć edycję oryginalnej odpowiedzi. Wypróbowałem ją wczoraj i podwójne sprawdzanie zapisywało mi twarz od złego w raportowaniu na poziomie Cxo. Wszystko, co musisz zrobić, to spróbować raz tej samej średniej kroczącej z "prawidłowym" i innym razem z "tym samym" - i gdy jesteś przekonany daj mi trochę miłości (aka-up-vote) – ekta

+0

Jestem obecnie w pracy, więc nie mam dostępu do Pythona, ale kiedy " W domu spróbuję :) –

27

Jak numpy.convolve jest dość powolny, którzy potrzebują szybkiego wykonywania rozwiązanie wolą łatwiejsze do zrozumienia cumSum podejście. Oto kod:

cumsum_vec = numpy.cumsum(numpy.insert(data, 0, 0)) 
ma_vec = (cumsum_vec[window_width:] - cumsum_vec[:-window_width])/window_width 

gdzie dane zawiera dane, a ma_vec będzie zawierać ruchome średnie window_width długości.

Średnio, cumsum jest około 30-40 razy szybszy niż convolve.

+2

Myślę, że jeśli dziś zaimplementuję średnią ruchomą w trybie offline, użyłbym twojego rozwiązania od samego początku, zamiast convolve. Właściwie to jestem zaskoczony, że ta odpowiedź nie otrzymała dużo więcej upvotes ... – heltonbiker

+0

gdzie jest parametr "krok"? –

+0

@ roman-kh, Byłbym wdzięczny, gdybyś mógł rzucić na to okiem i podziękować. https://stackoverflow.com/questions/45839123/python-how-can-we-smooth-a-noisy-signal-using-moving-Average –

0

Moja średnia ruchoma funkcji, bez numpy funkcji:

from __future__ import division # must be on first line of script 

class Solution: 
    def Moving_Avg(self,A): 
     m = A[0] 
     B = [] 
     B.append(m) 
     for i in range(1,len(A)): 
      m = (m * i + A[i])/(i+1) 
      B.append(m) 
     return B 
+0

Przepraszamy, aby dodać pierwszą linię: z _future_ import division.W przeciwnym razie wyjście będzie int zamiast float –

+0

@Arnanda_An, Możesz wymusić podział float w Pythonie 2, używając kropki dziesiętnej w '1':' m = (m * i + A [i])/(i + 1 .) ' –