Wenn ich einen Datensatz habe, der eine Grafik wie die folgende erzeugt, wie würde ich algorithmisch die x-Werte der angezeigten Peaks bestimmen (in diesem Fall drei davon):
Wenn ich einen Datensatz habe, der eine Grafik wie die folgende erzeugt, wie würde ich algorithmisch die x-Werte der angezeigten Peaks bestimmen (in diesem Fall drei davon):
Antworten:
Ein allgemeiner Ansatz besteht darin, die Daten zu glätten und dann Peaks zu finden, indem ein lokaler Maximalfilter mit dem Glättungsfilter verglichen wird . In R
:
argmax <- function(x, y, w=1, ...) {
require(zoo)
n <- length(y)
y.smooth <- loess(y ~ x, ...)$fitted
y.max <- rollapply(zoo(y.smooth), 2*w+1, max, align="center")
delta <- y.max - y.smooth[-c(1:w, n+1-1:w)]
i.max <- which(delta <= 0) + w
list(x=x[i.max], i=i.max, y.hat=y.smooth)
}
Sein Rückgabewert enthält die Argumente der lokalen Maxima ( x
) - die die Frage beantworten - und die Indizes in den x- und y-Arrays, in denen diese lokalen Maxima auftreten ( i
).
Es gibt zwei Parameter, die auf die Umstände abgestimmt werden müssen: w
Ist die halbe Fensterbreite, die zur Berechnung des lokalen Maximums verwendet wird. (Sein Wert sollte wesentlich kleiner als die Hälfte des Datenfelds sein.) Kleine Werte nehmen kleine lokale Unebenheiten auf, während größere Werte direkt über diese hinweggehen. Ein anderes - in diesem Code nicht explizit - ist das span
Argument des loess
Glätters. (Sie liegt normalerweise zwischen null und eins. Sie gibt die Fensterbreite als Anteil des Bereichs der x-Werte wieder.) Größere Werte glätten die Daten aggressiver und lassen lokale Unebenheiten vollständig verschwinden.
Um zu sehen, wie sich diese Optimierung auswirkt, erstellen wir eine kleine Testfunktion, um die Ergebnisse zu zeichnen:
test <- function(w, span) {
peaks <- argmax(x, y, w=w, span=span)
plot(x, y, cex=0.75, col="Gray", main=paste("w = ", w, ", span = ", span, sep=""))
lines(x, peaks$y.hat, lwd=2) #$
y.min <- min(y)
sapply(peaks$i, function(i) lines(c(x[i],x[i]), c(y.min, peaks$y.hat[i]),
col="Red", lty=2))
points(x[peaks$i], peaks$y.hat[peaks$i], col="Red", pch=19, cex=1.25)
}
Im Folgenden werden einige Experimente mit synthetischen, leicht verrauschten Daten durchgeführt.
x <- 1:1000 / 100 - 5
y <- exp(abs(x)/20) * sin(2 * x + (x/5)^2) + cos(10*x) / 5 + rnorm(length(x), sd=0.05)
par(mfrow=c(3,1))
test(2, 0.05)
test(30, 0.05)
test(2, 0.2)
Entweder ein breites Fenster (mittleres Diagramm) oder ein aggressiveres glattes Fenster (unteres Diagramm) eliminieren die lokalen Maxima, die im oberen Diagramm erkannt wurden. Die beste Kombination ist hier wahrscheinlich ein breites Fenster und nur eine sanfte Glättung, da eine aggressive Glättung diese Peaks zu verschieben scheint (sehen Sie die mittleren und rechten Punkte in der unteren Darstellung und vergleichen Sie ihre Positionen mit den scheinbaren Peaks der Rohdaten). In diesem Beispiel w=50
und span=0.05
macht einen tollen Job (nicht gezeigt).
Beachten Sie, dass die lokalen Maxima an den Endpunkten nicht erkannt werden. Diese können separat eingesehen werden. (Um dies zu unterstützen, werden argmax
die geglätteten y-Werte zurückgegeben.)
Dieser Ansatz hat mehrere Vorteile gegenüber einer formaleren Modellierung für allgemeine Zwecke:
Es wird kein vorgefasstes Modell der Daten übernommen.
Es kann an die Dateneigenschaften angepasst werden.
Es kann angepasst werden, um die Arten von Peaks zu erkennen, an denen man interessiert ist.
w
und zu ermitteln span
und um festzustellen, dass höhere Werte von span
die Spitzen verschoben haben. Es scheint, als könnten auch diese Schritte automatisiert werden. Wenn wir zum Beispiel für die erste Ausgabe die Qualität der entdeckten Peaks bewerten könnten, könnten wir optimize
mit den Parametern arbeiten! Wählen Sie für die zweite Ausgabe z. B. ein Fenster zu beiden Seiten des erkannten Peaks aus und suchen Sie nach höheren Werten.
Wie ich im Kommentar erwähnt habe, bietet ein harmonisches Regressionsmodell eine Möglichkeit, die Funktion zu glätten und den Peak zu identifizieren, indem der erste und der zweite Ableitungstest angewendet werden, wenn die Zeitreihe periodisch angepasst zu sein scheinen. Huber hat auf einen nichtparametrischen Test hingewiesen, der Vorteile hat, wenn es mehrere Peaks gibt und die Funktion nicht unbedingt periodisch ist. Es gibt aber kein kostenloses Mittagessen. Obwohl seine Methode die Vorteile aufweist, die er erwähnt, kann es Nachteile geben, wenn ein parametrisches Modell geeignet ist. Das ist immer die Kehrseite der Verwendung nichtparametrischer Techniken. Obwohl parametrische Annahmen vermieden werden, ist der parametrische Ansatz besser, wenn die parametrischen Annahmen angemessen sind. Sein Verfahren nutzt auch die Zeitreihenstruktur in den Daten nicht in vollem Umfang aus.
Ich denke, dass es zwar angebracht ist, die Vorteile eines vorgeschlagenen Verfahrens herauszustellen, es aber auch wichtig ist, die möglichen Nachteile herauszustellen. Sowohl mein Ansatz als auch der von Huber finden die Peaks auf effiziente Weise. Ich denke jedoch, dass sein Verfahren ein wenig mehr Arbeit erfordert, wenn ein lokales Maximum unter dem zuvor bestimmten höchsten Peak liegt.
Ein klassischer Ansatz zur Erkennung von Spitzenwerten in der Signalverarbeitung lautet wie folgt:
Ein anderer Ansatz, der funktioniert, besteht darin, ein scharf hochpassgefiltertes Signal mit einem stark geglätteten (tiefpass- oder mediangefilterten) Signal zu vergleichen und Schritt 3 anzuwenden.
Hoffe das hilft.