Können Sie eine Modulfunktion von numpy / scipy vorschlagen, die lokale Maxima / Minima in einem 1D-numpy-Array findet? Natürlich ist der einfachste Ansatz, einen Blick auf die nächsten Nachbarn zu werfen, aber ich hätte gerne eine akzeptierte Lösung, die Teil der numpy Distribution ist.
116
Antworten:
Wenn Sie nach allen Einträgen im 1d-Array suchen, die
a
kleiner als ihre Nachbarn sind, können Sie es versuchenSie können Ihr Array auch vor diesem Schritt mit glätten
numpy.convolve()
.Ich glaube nicht, dass es dafür eine spezielle Funktion gibt.
quelle
<
mit>
geben Ihnen die lokalen Maxima anstelle der Minima[False False]
Was könnte das Problem hier sein?In SciPy> = 0,11
Produziert
Beachten Sie, dass dies die Indizes von x sind, die lokal max / min sind. Um die Werte zu erhalten, versuchen Sie:
scipy.signal
bietet auchargrelmax
undargrelmin
zum Finden von Maxima bzw. Minima.quelle
np.random.random(12)
Erzeugt 12 Zufallswerte, die zur Demonstration der Funktion verwendet werdenargrelextrema
.test02=np.array([10,4,4,4,5,6,7,6])
, dann funktioniert es nicht. Die aufeinanderfolgenden Werte werden nicht als lokale Minima erkannt.Für Kurven mit nicht zu viel Rauschen empfehle ich das folgende kleine Code-Snippet:
Das
+1
ist wichtig, weildiff
die ursprüngliche Indexnummer reduziert wird.quelle
[1, 2, 2, 3, 3, 3, 2, 2, 1]
, liegen die lokalen Maxima offensichtlich irgendwo zwischen den 3en in der Mitte. Wenn Sie jedoch die von Ihnen bereitgestellten Funktionen ausführen, erhalten Sie Maxima bei den Indizes 2,6 und Minimas bei den Indizes 1,3,5,7, was für mich wenig sinnvoll ist.+1
anstatt zunp.diff()
verwendennp.gradient()
.Ein anderer Ansatz (mehr Wörter, weniger Code), der helfen kann:
Die Orte der lokalen Maxima und Minima sind auch die Orte der Nulldurchgänge der ersten Ableitung. Es ist im Allgemeinen viel einfacher, Nulldurchgänge zu finden, als lokale Maxima und Minima direkt zu finden.
Leider neigt die erste Ableitung dazu, das Rauschen zu "verstärken". Wenn also in den Originaldaten signifikantes Rauschen vorhanden ist, wird die erste Ableitung am besten erst verwendet, nachdem auf die Originaldaten ein gewisser Grad an Glättung angewendet wurde.
Da das Glätten im einfachsten Sinne ein Tiefpassfilter ist, wird das Glätten häufig am besten (am einfachsten) unter Verwendung eines Faltungskerns durchgeführt, und das "Formen" dieses Kernels kann eine überraschende Menge an Funktionen zum Erhalten / Verbessern von Merkmalen bereitstellen . Der Prozess des Findens eines optimalen Kernels kann mit einer Vielzahl von Mitteln automatisiert werden, aber das Beste kann einfache Brute Force sein (viel schnell, um kleine Kernel zu finden). Ein guter Kernel wird (wie beabsichtigt) die Originaldaten massiv verzerren, aber NICHT die Position der interessierenden Spitzen / Täler beeinflussen.
Glücklicherweise kann ziemlich oft ein geeigneter Kernel über eine einfache SWAG ("fundierte Vermutung") erstellt werden. Die Breite des Glättungskerns sollte etwas breiter sein als der breiteste erwartete "interessante" Peak in den Originaldaten, und seine Form ähnelt diesem Peak (einem einskalierten Wavelet). Für mittelschonende Kernel (was ein guter Glättungsfilter sein sollte) sollte die Summe der Kernelelemente genau gleich 1,00 sein, und der Kernel sollte symmetrisch zu seiner Mitte sein (was bedeutet, dass er eine ungerade Anzahl von Elementen hat.
Bei einem optimalen Glättungskern (oder einer kleinen Anzahl von Kerneln, die für unterschiedliche Dateninhalte optimiert sind) wird der Grad der Glättung zu einem Skalierungsfaktor für (den "Gewinn") des Faltungskerns.
Die Bestimmung des "richtigen" (optimalen) Glättungsgrades (Faltungskernverstärkung) kann sogar automatisiert werden: Vergleichen Sie die Standardabweichung der Daten der ersten Ableitung mit der Standardabweichung der geglätteten Daten. Wie sich das Verhältnis der beiden Standardabweichungen mit Änderungen des Glättungsgrads ändert, kann verwendet werden, um effektive Glättungswerte vorherzusagen. Ein paar manuelle Datenläufe (die wirklich repräsentativ sind) sollten alles sein, was benötigt wird.
Alle oben aufgeführten früheren Lösungen berechnen die erste Ableitung, behandeln sie jedoch weder als statistisches Maß, noch versuchen die oben genannten Lösungen, die Glättung von Merkmalen zu erhalten / zu verbessern (um subtilen Spitzen zu helfen, über das Rauschen zu "springen").
Schließlich die schlechte Nachricht: Das Finden von "echten" Peaks wird zu einem königlichen Schmerz, wenn das Rauschen auch Merkmale aufweist, die wie echte Peaks aussehen (überlappende Bandbreite). Die nächste komplexere Lösung besteht im Allgemeinen darin, einen längeren Faltungskern (eine "breitere Kernelöffnung") zu verwenden, der die Beziehung zwischen benachbarten "realen" Peaks (wie minimale oder maximale Raten für das Auftreten von Peaks) berücksichtigt, oder mehrere zu verwenden Faltungsdurchläufe werden mit Kerneln unterschiedlicher Breite durchgeführt (aber nur, wenn es schneller ist: Es ist eine grundlegende mathematische Wahrheit, dass nacheinander durchgeführte lineare Faltungen immer zusammen zu einer einzigen Faltung gefaltet werden können). Es ist jedoch oft viel einfacher, zuerst eine Folge nützlicher Kernel (unterschiedlicher Breite) zu finden und sie zusammenzufalten, als den endgültigen Kernel in einem einzigen Schritt direkt zu finden.
Hoffentlich bietet dies genügend Informationen, damit Google (und möglicherweise ein guter Statistiktext) die Lücken füllen kann. Ich wünschte wirklich, ich hätte die Zeit, ein funktionierendes Beispiel oder einen Link zu einem zu liefern. Wenn jemand online auf eines stößt, poste es bitte hier!
quelle
Ab SciPy Version 1.1 können Sie auch find_peaks verwenden . Nachfolgend finden Sie zwei Beispiele aus der Dokumentation.
Mit dem
height
Argument können alle Maxima über einem bestimmten Schwellenwert ausgewählt werden (in diesem Beispiel alle nicht negativen Maxima; dies kann sehr nützlich sein, wenn man sich mit einer verrauschten Grundlinie befassen muss; wenn Sie Minima finden möchten, multiplizieren Sie einfach Ihre Eingabe von-1
):Ein weiteres äußerst hilfreiches Argument ist
distance
, das den Mindestabstand zwischen zwei Spitzen definiert:quelle
Warum nicht die in Scipy integrierte Funktion signal.find_peaks_cwt verwenden , um die Arbeit zu erledigen?
Ergebnisse:
Grüße
quelle
Update: Ich war mit dem Farbverlauf nicht zufrieden und fand es daher zuverlässiger
numpy.diff
. Bitte lassen Sie mich wissen, ob es tut, was Sie wollen.In Bezug auf das Problem des Rauschens besteht das mathematische Problem darin, Maxima / Minima zu lokalisieren, wenn wir das Rauschen betrachten wollen, können wir so etwas wie Faltung verwenden, das zuvor erwähnt wurde.
quelle
Während diese Frage wirklich alt ist. Ich glaube, es gibt einen viel einfacheren Ansatz bei Numpy (einem Einzeiler).
Um ein lokales Maximum oder Min zu finden, möchten wir im Wesentlichen herausfinden, wann sich die Differenz zwischen den Werten in der Liste (3-1, 9-3 ...) von positiv zu negativ (max) oder negativ zu positiv (min) ändert. Deshalb finden wir zuerst den Unterschied. Dann finden wir das Zeichen, und dann finden wir die Zeichenänderungen, indem wir den Unterschied erneut nehmen. (Ähnlich wie bei einer ersten und zweiten Ableitung im Kalkül haben nur wir diskrete Daten und keine stetige Funktion.)
Die Ausgabe in meinem Beispiel enthält nicht die Extrema (den ersten und den letzten Wert in der Liste). Ebenso wie beim Kalkül haben Sie, wenn die zweite Ableitung negativ ist, max und wenn sie positiv ist, haben Sie eine min.
Somit haben wir folgendes Matchup:
quelle
Keine dieser Lösungen funktionierte für mich, da ich auch Spitzenwerte im Zentrum sich wiederholender Werte finden wollte. zum Beispiel in
ar = np.array([0,1,2,2,2,1,3,3,3,2,5,0])
Die Antwort sollte sein
Ich habe das mit einer Schleife gemacht. Ich weiß, dass es nicht super sauber ist, aber es erledigt den Job.
quelle
minm
undmaxm
enthalten Indizes von Minima bzw. Maxima. Bei einem großen Datensatz werden viele Maxima / Minimas angegeben. In diesem Fall wird die Kurve zuerst geglättet und dann dieser Algorithmus angewendet.quelle
Eine andere Lösung, die im Wesentlichen einen erweiterten Operator verwendet:
und für die Minima:
Auch von können
scipy.ndimage
Sierank_filter(x, -1, size=3)
mitgrey_dilation
undrank_filter(x, 0, size=3)
mit ersetzengrey_erosion
. Dies erfordert keine lokale Sortierung und ist daher etwas schneller.quelle
Noch einer:
quelle