Hier ist mein Experiment:
Ich benutze die findPeaks
Funktion im quantmod- Paket:
Ich möchte "lokale" Peaks innerhalb einer Toleranz 5 erkennen, dh die ersten Stellen nach der Zeitreihe fallen um 5 von den lokalen Peaks ab:
aa=100:1
bb=sin(aa/3)
cc=aa*bb
plot(cc, type="l")
p=findPeaks(cc, 5)
points(p, cc[p])
p
Die Ausgabe ist
[1] 3 22 41
Es scheint falsch, da ich mehr "lokale Spitzen" als 3 erwarte ...
Irgendwelche Gedanken?
r
time-series
Luna
quelle
quelle
findPeaks
erscheint in meiner Antwort, @Adam. Übrigens ist das Paket "quantmod" .Antworten:
Die Quelle dieses Codes wird durch Eingabe seines Namens an der R-Eingabeaufforderung ermittelt. Die Ausgabe ist
Der Test
x[pks - 1] - x[pks] > thresh
vergleicht jeden Spitzenwert mit dem Wert, der ihm unmittelbar in der Reihe folgt (nicht mit dem nächsten Tiefpunkt in der Reihe). Es verwendet eine (grobe) Schätzung der Größe der Steigung der Funktion unmittelbar nach dem Peak und wählt nur die Peaks aus, bei denen diese Steigung diethresh
Größe überschreitet . In Ihrem Fall sind nur die ersten drei Peaks scharf genug, um den Test zu bestehen. Sie erkennen alle Peaks anhand der Standardeinstellung:quelle
Ich stimme der Antwort von whuber zu, wollte aber nur hinzufügen, dass der "+2" -Teil des Codes, der versucht, den Index zu verschieben, um dem neu gefundenen Peak zu entsprechen, tatsächlich "überschießt" und "+1" sein sollte. Im vorliegenden Beispiel erhalten wir zum Beispiel:
Wenn wir diese gefundenen Peaks in einem Diagramm hervorheben (fett rot):
wir sehen, dass sie konstant 1 Punkt vom tatsächlichen Peak entfernt sind.
Konsequenz
sollte
pks[x[pks] - x[pks + 1] > thresh]
oder seinpks[x[pks] - x[pks - 1] > thresh]
GROSSES UPDATE
Nach meiner eigenen Suche nach einer adäquaten Peak-Finding-Funktion habe ich folgendes geschrieben:
Ein „Peak“ ist definiert als ein lokales Maximum, bei dem die
m
Punkte auf beiden Seiten kleiner sind als es.m
Je größer der Parameter , desto strenger ist daher das Spitzenfinanzierungsverfahren. so:Die Funktion kann auch verwendet werden, um lokale Minima eines sequentiellen Vektors
x
über zu findenfind_peaks(-x)
.Hinweis: Ich habe jetzt die Funktion auf gitHub gesetzt, falls jemand sie benötigt: https://github.com/stas-g/findPeaks
quelle
Eek: Kleines Update. Ich musste zwei Codezeilen, die Grenzen, ändern (ein -1 und ein +1 hinzufügen), um die Gleichwertigkeit mit der Funktion von Stas_G zu erreichen (es wurden einige zu viele zusätzliche Peaks in realen Datensätzen gefunden). Entschuldigungen für irgendjemanden, der von meinem ursprünglichen Beitrag nur geringfügig abgekommen ist.
Ich verwende den Stas_g-Algorithmus zum Auffinden von Peaks seit einiger Zeit. Für eines meiner späteren Projekte war es mir wegen seiner Einfachheit von Vorteil. Ich musste es jedoch millionenfach für eine Berechnung verwenden, damit ich es in Rcpp umschrieb (siehe Rcpp-Paket). In einfachen Tests ist es ungefähr 6x schneller als die R-Version. Wenn jemand interessiert ist, habe ich den Code unten hinzugefügt. Hoffentlich helfe ich jemandem, Prost!
Einige kleine Vorbehalte. Diese Funktion gibt Spitzenindizes in umgekehrter Reihenfolge des R-Codes zurück. Es erfordert eine interne C ++ - Signierfunktion, die ich integriert habe. Es wurde nicht vollständig optimiert, aber weitere Leistungssteigerungen werden nicht erwartet.
quelle
for(q = lb; q < rb; ++q){ if(vY(q) > vY(i+1)){ isGreatest = false; } }
der letzte Durchlauf der Schleife "gewinnt", wird das Äquivalent von: ausgeführtisGreatest = vY(rb-1) <= vY(rb)
. Um das zu erreichen, was der Kommentar direkt über dieser Zeile aussagt, müsste die for-Schleife geändert werden in:for(q = lb; isGreatest && (q < rb); ++q){ isGreatest = (vY(q) <= vY(i+1)) }
Erstens: Der Algorithmus ruft fälschlicherweise einen Drop rechts von einem flachen Plateau auf, da
sign(diff(x, na.pad = FALSE))
er 0 und dann -1 ist, sodass sein Diff ebenfalls -1 ist. Eine einfache Lösung besteht darin, sicherzustellen, dass das Vorzeichen vor dem negativen Eintrag nicht null, sondern positiv ist:Zweitens: Der Algorithmus liefert sehr lokale Ergebnisse, z. B. ein "Auf", gefolgt von einem "Ab" in jedem Lauf von drei aufeinanderfolgenden Begriffen in der Sequenz. Wenn man sich stattdessen für lokale Maxima einer gestörten kontinuierlichen Funktion interessiert, dann - gibt es wahrscheinlich andere bessere Dinge da draußen, aber dies ist meine billige und sofortige Lösung
um die Daten ein wenig zu glätten. Verwenden Sie auch die oben erwähnte Kontrolle gegen Flach- und Abfall.
Filtern Sie diese Kandidaten, indem Sie für eine Version mit Lössglättung den Durchschnitt innerhalb eines Fensters, das an jedem Peak zentriert ist, mit dem Durchschnitt der lokalen Begriffe außerhalb des Fensters vergleichen.
quelle
Es ist wahr, dass die Funktion auch das Ende von Plateaus identifiziert, aber ich denke, dass es eine andere einfachere Lösung gibt: Da der erste Diff eines realen Peaks '1' ergibt, dann '-1', wäre der zweite Diff '-2', und wir können direkt überprüfen
quelle