Oto mój eksperyment:
Korzystam z findPeaks
funkcji w pakiecie quantmod :
Chcę wykryć „lokalne” piki w granicach tolerancji 5, tj. Pierwsze lokalizacje po spadku szeregów czasowych od lokalnych pików o 5:
aa=100:1
bb=sin(aa/3)
cc=aa*bb
plot(cc, type="l")
p=findPeaks(cc, 5)
points(p, cc[p])
p
Dane wyjściowe to
[1] 3 22 41
Wydaje się nie tak, ponieważ spodziewam się więcej „lokalnych szczytów” niż 3 ...
jakieś pomysły?
r
time-series
Luna
źródło
źródło
findPeaks
pojawia się w mojej odpowiedzi @Adam. BTW, pakiet to „quantmod” .Odpowiedzi:
Źródło tego kodu można uzyskać, wpisując jego nazwę w wierszu polecenia R. Dane wyjściowe to
Test
x[pks - 1] - x[pks] > thresh
porównuje każdą wartość szczytową z wartością, która natychmiast zastępuje ją w szeregu (nie do następnego dołka w szeregu). Wykorzystuje (przybliżone) oszacowanie wielkości nachylenia funkcji bezpośrednio po szczycie i wybiera tylko te piki, których nachylenie przekraczathresh
rozmiar. W twoim przypadku tylko pierwsze trzy piki są wystarczająco ostre, aby przejść test. Wykryjesz wszystkie szczyty, używając domyślnego:źródło
Zgadzam się z odpowiedzią Whubera, ale chciałem tylko dodać, że część „+2” kodu, która próbuje przesunąć indeks w celu dopasowania do nowo znalezionego szczytu, w rzeczywistości „przekracza” i powinna wynosić „+1”. na przykład w omawianym przykładzie otrzymujemy:
kiedy zaznaczymy te znalezione piki na wykresie (pogrubiona czerwona):
widzimy, że są one konsekwentnie 1 punkt od rzeczywistego szczytu.
konsekwencja
powinien być
pks[x[pks] - x[pks + 1] > thresh]
lubpks[x[pks] - x[pks - 1] > thresh]
DUŻA AKTUALIZACJA
podążając za własną misją znalezienia odpowiedniej funkcji znajdowania pików, napisałem to:
„szczyt” jest zdefiniowany jako lokalne maksima, przy czym
m
punkty po obu jego stronach są mniejsze od niego. stąd im większy parametrm
, tym bardziej rygorystyczna jest procedura finansowania szczytowego. więc:funkcja może być również wykorzystana do znalezienia lokalnych minimów dowolnego wektora sekwencyjnego
x
poprzezfind_peaks(-x)
.Uwaga: teraz umieściłem tę funkcję na gitHub, jeśli ktoś jej potrzebuje: https://github.com/stas-g/findPeaks
źródło
Eek: Drobna aktualizacja. Musiałem zmienić dwa wiersze kodu, granice (dodać -1 i +1), aby osiągnąć równoważność z funkcją Stas_G (znajdowało kilka zbyt wielu „dodatkowych pików” w prawdziwych zestawach danych). Przepraszam za każdego, kto bardzo nieznacznie sprowadził mój oryginalny post.
Od dłuższego czasu korzystam z algorytmu znajdowania szczytów Stas_g. Był korzystny dla jednego z moich późniejszych projektów ze względu na jego prostotę. Musiałem jednak użyć go miliony razy do obliczeń, więc przepisałem go w Rcpp (patrz pakiet Rcpp). W prostych testach jest około 6 razy szybszy niż wersja R. Jeśli ktoś jest zainteresowany, dodałem poniższy kod. Mam nadzieję, że komuś pomogę, zdrowie!
Kilka drobnych zastrzeżeń. Ta funkcja zwraca indeksy szczytowe w odwrotnej kolejności do kodu R. Wymaga wbudowanej funkcji C ++ Sign, którą załączyłem. Nie został on w pełni zoptymalizowany, ale nie należy spodziewać się dalszego wzrostu wydajności.
źródło
for(q = lb; q < rb; ++q){ if(vY(q) > vY(i+1)){ isGreatest = false; } }
jako ostatniego przejazdu przez pętlę „wygrywa”, robi równowartość:isGreatest = vY(rb-1) <= vY(rb)
. Aby osiągnąć to, co twierdzi komentarz tuż powyżej tej linii, pętla for musiałaby zostać zmieniona na:for(q = lb; isGreatest && (q < rb); ++q){ isGreatest = (vY(q) <= vY(i+1)) }
Po pierwsze: algorytm również fałszywie wywołuje kroplę po prawej stronie płaskiego płaskowyżu, ponieważ
sign(diff(x, na.pad = FALSE))
będzie wynosił 0, a następnie -1, więc jej różnica również będzie wynosić -1. Prostą poprawką jest upewnienie się, że różnica znaków poprzedzająca wpis ujemny nie jest równa zero, ale dodatnia:Po drugie: algorytm daje bardzo lokalne wyniki, np. „Góra”, po której następuje „dół” w dowolnym szeregu trzech kolejnych wyrazów w sekwencji. Jeśli zamiast tego interesują się lokalne maksima dźwiękowej funkcji ciągłej, to prawdopodobnie istnieją inne lepsze rzeczy, ale jest to moje tanie i natychmiastowe rozwiązanie
nieznacznie wygładzić dane. Zastosuj również wyżej wspomnianą kontrolę przeciwko płaskiemu, a następnie wypadnięciu.
filtruj tych kandydatów, porównując, dla wersji z wygładzoną warstwą, średnią w oknie wyśrodkowaną na każdym szczycie ze średnią lokalnych warunków na zewnątrz.
źródło
To prawda, że funkcja identyfikuje także koniec płaskowyżów, ale myślę, że jest jeszcze jedna łatwiejsza poprawka: ponieważ pierwsza różnica rzeczywistego piku spowoduje „1”, a następnie „-1”, druga różnica będzie mieć „-2”, i możemy to sprawdzić bezpośrednio
źródło
używając Numpy
lub
za pomocą pand
źródło