Wydaje się, że nie ma funkcji, która po prostu oblicza średnią ruchomą na numpy / scipy, co prowadzi do zawiłych rozwiązań .
Moje pytanie jest dwojakie:
- Jaki jest najłatwiejszy sposób (poprawnie) zaimplementowania średniej ruchomej za pomocą numpy?
- Ponieważ wydaje się to nietrywialne i podatne na błędy, czy istnieje dobry powód, aby nie uwzględniać baterii w tym przypadku?
python
numpy
scipy
time-series
moving-average
goncalopp
źródło
źródło
Odpowiedzi:
Jeśli chcesz po prostu prosty non-ważona średnia ruchoma, można łatwo wdrożyć go
np.cumsum
, comoże byćto metody oparte szybciej niż FFT:EDYCJA Poprawiono błędne indeksowanie, które Bean wykrył w kodzie. EDYTOWAĆ
Więc myślę, że odpowiedź brzmi: jest naprawdę łatwy do wdrożenia, a może numpy jest już trochę nadęty ze specjalistyczną funkcjonalnością.
źródło
ret[n:] -= ret[:-n]
NIE JEST TO SAMO jakret[n:] = ret[n:] - ret[:-n]
. Poprawiłem kod w tej odpowiedzi. Edycja: Nie, ktoś inny po prostu mnie pokonał.Brak w NumPy konkretnej funkcji specyficznej dla domeny jest prawdopodobnie spowodowany dyscypliną i wiernością Głównego Zespołu Podstawowej Dyrektywie NumPy: zapewnić N-wymiarowy typ tablicy , a także funkcje do tworzenia i indeksowania tych tablic. Podobnie jak wiele podstawowych celów, ten nie jest mały, a NumPy robi to znakomicie.
(O wiele) większy SciPy zawiera znacznie większy zbiór bibliotek specyficznych dla domeny (nazywanych przez twórców SciPy podpakietami ) - na przykład optymalizacja numeryczna ( optymalizacja ), przetwarzanie sygnału ( sygnał ) i rachunek całkowy ( integracja ).
Domyślam się, że funkcja, której szukasz, znajduje się w co najmniej jednym z podpakietów SciPy ( być może scipy.signal ); jednak najpierw zajrzałbym do kolekcji SciPy scikits , zidentyfikowałbym odpowiedni (e) scikit (y) i poszukał interesującej mnie funkcji.
Scikity to niezależnie opracowane pakiety oparte na NumPy / SciPy i skierowane do określonej dyscypliny technicznej (np. Scikits-image , scikits-learn itp.) Kilka z nich (w szczególności niesamowity OpenOpt do optymalizacji numerycznej) zostało wysoko ocenionych, dojrzałe projekty na długo przed podjęciem decyzji o zamieszkaniu w stosunkowo nowej rubryce scikits . Strona główna Scikits powyżej zawiera około 30 takich scikitów , chociaż przynajmniej kilka z nich nie jest już w fazie aktywnego rozwoju.
Postępowanie zgodnie z tą radą doprowadziłoby cię do serii scikits ; jednak pakiet ten nie jest już aktywnie rozwijany; W efekcie Pandy stały się, AFAIK, de facto biblioteką szeregów czasowych opartą na NumPy .
Pandy ma kilka funkcji, których można użyć do obliczenia średniej ruchomej ; najprostszym z nich jest prawdopodobnie rolling_mean , którego używasz w ten sposób:
Teraz wystarczy wywołać funkcję rolling_mean przekazującą obiekt Series i rozmiar okna , który w moim przykładzie poniżej wynosi 10 dni .
sprawdzić, czy zadziałało - np. porównać wartości 10-15 w oryginalnej serii z nową serią wygładzoną za pomocą średniej kroczącej
Funkcja rolling_mean wraz z kilkunastoma innymi funkcjami jest nieformalnie zgrupowana w dokumentacji Pandy pod rubryką „ Funkcje ruchomego okna” ; druga, powiązana grupa funkcji w Pandas jest określana jako funkcje ważone wykładniczo (np. ewma , która oblicza wykładniczo ruchomą średnią ważoną). Fakt, że ta druga grupa nie jest zawarta w pierwszej ( funkcje ruchomego okna ) jest prawdopodobnie spowodowana tym, że transformacje ważone wykładniczo nie opierają się na oknie o stałej długości
źródło
Prostym sposobem na osiągnięcie tego jest użycie
np.convolve
. Ideą tego jest wykorzystanie sposobu obliczania splotu dyskretnego i wykorzystanie go do zwrócenia średniej kroczącej . Można to zrobić przez splatanie z sekwencją onp.ones
długości równej długości przesuwanego okna, jakiej chcemy.W tym celu możemy zdefiniować następującą funkcję:
Ta funkcja będzie pobierać splot ciągu
x
i sekwencję długościw
. Zwróć uwagę, że wybranamode
jestvalid
taka, że iloczyn splotu jest podawany tylko dla punktów, w których sekwencje całkowicie się pokrywają.Kilka przykładów:
Dla średniej ruchomej z oknem długości
2
mielibyśmy:A dla okna o długości
4
:Jak to
convolve
działa?Przyjrzyjmy się dokładniej sposobowi obliczania splotu dyskretnego. Następująca funkcja ma na celu odtworzenie sposobu
np.convolve
obliczania wartości wyjściowych:Co, dla tego samego przykładu powyżej, również dałoby:
Więc to, co jest robione na każdym kroku, to wzięcie iloczynu wewnętrznego między tablicą jedynek a bieżącym oknem . W tym przypadku mnożenie przez
np.ones(w)
jest zbędne, biorąc pod uwagę, że bezpośrednio bierzemysum
ciąg.Poniżej znajduje się przykład tego, jak obliczane są pierwsze wyniki, aby było trochę jaśniej. Załóżmy, że chcemy mieć okno
w=4
:A następujący wynik zostałby obliczony jako:
I tak dalej, zwracając średnią ruchomą sekwencji po wykonaniu wszystkich nałożeń.
źródło
mode='valid'
można zastąpić'same'
. Właśnie w tym przypadku punkty krawędziowe będą grawitować w kierunku zera.Oto kilka sposobów, aby to zrobić, wraz z niektórymi wzorcami. Najlepsze metody to wersje korzystające ze zoptymalizowanego kodu z innych bibliotek.
bottleneck.move_mean
Metoda jest prawdopodobnie najlepiej dookoła.scipy.convolve
Podejście jest również bardzo szybki, rozszerzalny i składniowo i koncepcyjnie proste, ale nie jest dobrze skalować dla bardzo dużych wartości okiennych.numpy.cumsum
Metoda jest dobra, jeśli potrzebujemy czystegonumpy
podejścia.Uwaga: niektóre z nich (np.
bottleneck.move_mean
) Nie są wyśrodkowane i spowodują przesunięcie danych.Czas, małe okno (n = 3)
Rozrząd, duże okno (n = 1001)
Pamięć, małe okno (n = 3)
Pamięć, duże okno (n = 1001)
źródło
Ta odpowiedź za pomocą Pand jest dostosowana z góry, ponieważ
rolling_mean
nie jest już częścią PandTeraz po prostu wywołaj funkcję
rolling
w ramce danych z rozmiarem okna, który w moim przykładzie poniżej wynosi 10 dni.źródło
Czuję, że można to łatwo rozwiązać za pomocą wąskiego gardła
Zobacz podstawowy przykład poniżej:
Daje to średnią ruchu wzdłuż każdej osi.
„mm” jest ruchomą średnią dla „a”.
„okno” to maksymalna liczba wpisów do rozważenia w przypadku średniej ruchomej.
„min_count” to minimalna liczba wpisów do rozważenia przy ruchomej średniej (np. dla pierwszego elementu lub jeśli tablica ma wartości nan).
Zaletą jest to, że wąskie gardło pomaga radzić sobie z wartościami nan, a także jest bardzo wydajne.
źródło
Jeśli chcesz uważnie zadbać o warunki brzegowe ( oblicz średnią tylko z dostępnych elementów na krawędziach ), poniższa funkcja załatwi sprawę .
źródło
Wypróbuj ten fragment kodu. Myślę, że to prostsze i spełnia swoje zadanie. okres ważności to okno średniej ruchomej.
W sekcji
Data[i-lookback:i, 0].sum()
umieściłem0
odniesienie do pierwszej kolumny zbioru danych, ale możesz umieścić dowolną kolumnę, jeśli masz więcej niż jedną kolumnę.źródło
Właściwie chciałem trochę innego zachowania niż zaakceptowana odpowiedź. Budowałem ekstraktor funkcji średniej ruchomej dla
sklearn
potoku, więc wymagałem, aby dane wyjściowe średniej ruchomej miały taki sam wymiar jak dane wejściowe. Chcę, aby średnia ruchoma zakładała, że szereg pozostaje stały, tj. Dałby średnią ruchomą[1,2,3,4,5]
z okna 2[1.5,2.5,3.5,4.5,5.0]
.W przypadku wektorów kolumnowych (mój przypadek użycia) otrzymujemy
I dla tablic
Oczywiście nie trzeba przyjmować stałych wartości wypełnienia, ale w większości przypadków powinno to być wystarczające.
źródło
talib zawiera proste narzędzie średniej ruchomej, a także inne podobne narzędzia do uśredniania (np. wykładnicza średnia ruchoma). Poniżej porównuje tę metodę z niektórymi innymi rozwiązaniami.
Jedynym zastrzeżeniem jest to, że rzeczywistość musi zawierać elementy
dtype = float
. W przeciwnym razie zgłaszany jest następujący błądźródło
Oto szybka implementacja przy użyciu numba (pamiętaj o typach). Zauważ, że zawiera nans, gdzie został przesunięty.
źródło
źródło
Używam albo rozwiązania zaakceptowanej odpowiedzi , nieco zmodyfikowanej, aby mieć taką samą długość danych wyjściowych jak dane wejściowe, lub
pandas
wersji, jak wspomniano w komentarzu do innej odpowiedzi. Podsumowuję tutaj oba z powtarzalnym przykładem do wykorzystania w przyszłości:źródło
Porównując poniższe rozwiązanie z rozwiązaniem wykorzystującym sumę numpy, zajmuje to prawie połowę czasu . Dzieje się tak, ponieważ nie musi przechodzić przez całą tablicę, aby obliczyć sumę, a następnie wykonać wszystkie odejmowanie. Ponadto suma może być „ niebezpieczna ”, jeśli tablica jest ogromna, a liczba jest ogromna ( możliwe przepełnienie ). Oczywiście, także tutaj istnieje niebezpieczeństwo, ale przynajmniej sumują się tylko istotne liczby.
źródło