Ich möchte den Durchschnitt eines Satzes kreisförmiger Daten berechnen. Zum Beispiel könnte ich mehrere Beispiele aus dem Lesen eines Kompasses haben. Das Problem ist natürlich, wie man mit dem Wraparound umgeht. Der gleiche Algorithmus kann für ein Zifferblatt nützlich sein.
Die eigentliche Frage ist komplizierter - was bedeuten Statistiken auf einer Kugel oder in einem algebraischen Raum, der sich "umhüllt", z. B. der additiven Gruppe mod n. Die Antwort ist möglicherweise nicht eindeutig, z. B. könnte der Durchschnitt von 359 Grad und 1 Grad 0 Grad oder 180 Grad sein, aber statistisch gesehen sieht 0 besser aus.
Dies ist ein echtes Programmierproblem für mich und ich versuche, es nicht nur wie ein mathematisches Problem aussehen zu lassen.
Antworten:
Berechnen Sie Einheitsvektoren aus den Winkeln und nehmen Sie den Winkel ihres Durchschnitts.
quelle
Diese Frage wird im Buch "Statistics On Spheres", Geoffrey S. Watson, Vorlesungsnotizen der Universität von Arkansas in den mathematischen Wissenschaften, 1983, John Wiley & Sons, Inc., ausführlich untersucht, wie unter http: //catless.ncl erwähnt. ac.uk/Risks/7.44.html#subj4 von Bruce Karsh.
Ein guter Weg, um einen durchschnittlichen Winkel A aus einer Reihe von Winkelmessungen a [i] 0 <= i zu schätzen
Die von starblue angegebene Methode ist rechnerisch äquivalent, aber seine Gründe sind klarer und wahrscheinlich programmatisch effizienter und funktionieren auch im Nullfall gut, also ein großes Lob an ihn.
Das Thema wird nun in Wikipedia und mit anderen Verwendungszwecken, wie z. B. Bruchteilen, ausführlicher untersucht .
quelle
Ich sehe das Problem - wenn Sie zum Beispiel einen Winkel von 45 'und einen Winkel von 315' haben, wäre der "natürliche" Durchschnitt 180 ', aber der gewünschte Wert ist tatsächlich 0'.
Ich denke, Starblue ist auf etwas. Berechnen Sie einfach die (x, y) kartesischen Koordinaten für jeden Winkel und addieren Sie die resultierenden Vektoren. Der Winkelversatz des endgültigen Vektors sollte Ihr gewünschtes Ergebnis sein.
Ich ignoriere vorerst, dass eine Kompassrichtung im Norden beginnt und im Uhrzeigersinn verläuft, während "normale" kartesische Koordinaten entlang der X-Achse mit Null beginnen und dann gegen den Uhrzeigersinn verlaufen. Die Mathematik sollte unabhängig davon auf die gleiche Weise funktionieren.
quelle
cos()
,sin()
undatan2()
gibt Annäherungen (gute, aber aus noch durch 1 oder 2 ULPs) Je mehr Sie also im Durchschnitt, desto mehr Fehler Sie umfassen.FÜR DEN BESONDEREN FALL VON ZWEI WINKELN:
Die Antwort ((a + b) mod 360) / 2 ist FALSCH . Für die Winkel 350 und 2 ist der nächste Punkt 356, nicht 176.
Die Einheitsvektor- und Triggerlösungen können zu teuer sein.
Was ich von einem kleinen Basteln habe, ist:
quelle
ackb hat recht, dass diese vektorbasierten Lösungen nicht als echte Durchschnittswerte von Winkeln betrachtet werden können, sondern nur ein Durchschnitt der Einheitsvektor-Gegenstücke sind. Die von ackb vorgeschlagene Lösung scheint jedoch mathematisch nicht zu klingen.
Das Folgende ist eine Lösung, die mathematisch aus dem Ziel der Minimierung (Winkel [i] - avgAngle) ^ 2 (wobei die Differenz gegebenenfalls korrigiert wird) abgeleitet wird, was sie zu einem echten arithmetischen Mittel der Winkel macht.
Zunächst müssen wir uns genau ansehen, in welchen Fällen sich der Unterschied zwischen den Winkeln von dem Unterschied zwischen ihren Gegenstücken mit normaler Anzahl unterscheidet. Betrachten Sie die Winkel x und y. Wenn y> = x - 180 und y <= x + 180, können wir die Differenz (xy) direkt verwenden. Andernfalls müssen wir (y + 360) anstelle von y in der Berechnung verwenden, wenn die erste Bedingung nicht erfüllt ist. Entsprechend müssen wir (y-360) anstelle von y verwenden, wenn die zweite Bedingung nicht erfüllt ist. Da sich die Gleichung der Kurve nur an den Punkten minimiert, an denen sich diese Ungleichungen von wahr zu falsch oder umgekehrt ändern, können wir den gesamten [0,360] -Bereich in eine Reihe von Segmenten unterteilen, die durch diese Punkte getrennt sind. Dann müssen wir nur das Minimum jedes dieser Segmente und dann das Minimum des Minimums jedes Segments finden, das der Durchschnitt ist.
Hier ist ein Bild, das zeigt, wo die Probleme bei der Berechnung von Winkeldifferenzen auftreten. Wenn x im grauen Bereich liegt, liegt ein Problem vor.
Um eine Variable zu minimieren, können wir abhängig von der Kurve die Ableitung dessen nehmen, was wir minimieren möchten, und dann den Wendepunkt finden (an dem die Ableitung = 0 ist).
Hier wenden wir die Idee an, die quadratische Differenz zu minimieren, um die gemeinsame arithmetische Mittelwertformel abzuleiten: sum (a [i]) / n. Die Kurve y = Summe ((a [i] -x) ^ 2) kann auf folgende Weise minimiert werden:
Wenden Sie es nun auf Kurven mit unseren angepassten Differenzen an:
b = Teilmenge von a, wobei die richtige (Winkel-) Differenz a [i] -xc = Teilmenge von a, wo die richtige (Winkel-) Differenz (a [i] -360) -x cn = Größe von cd = Teilmenge von a, wo die korrekte (Winkel-) Differenz (a [i] +360) -x dn = Größe von d
Dies allein reicht nicht aus, um das Minimum zu erreichen, während es für normale Werte mit einer unbegrenzten Menge funktioniert. Das Ergebnis liegt also definitiv im Bereich der Menge und ist daher gültig. Wir brauchen das Minimum innerhalb eines Bereichs (definiert durch das Segment). Wenn das Minimum kleiner als die Untergrenze unseres Segments ist, muss das Minimum dieses Segments an der Untergrenze liegen (da quadratische Kurven nur 1 Wendepunkt haben), und wenn das Minimum größer als die Obergrenze unseres Segments ist, liegt das Minimum des Segments bei obere Grenze. Nachdem wir das Minimum für jedes Segment haben, finden wir einfach dasjenige, das den niedrigsten Wert für das hat, was wir minimieren (Summe ((b [i] -x) ^ 2) + Summe (((c [i] -360)))) ) -b) ^ 2) + Summe (((d [i] +360) -c) ^ 2)).
Hier ist ein Bild der Kurve, das zeigt, wie sie sich an den Punkten ändert, an denen x = (a [i] +180)% 360 ist. Der fragliche Datensatz ist {65,92,230,320,250}.
Hier ist eine Implementierung des Algorithmus in Java, einschließlich einiger Optimierungen, seine Komplexität ist O (nlogn). Sie kann auf O (n) reduziert werden, wenn Sie die vergleichsbasierte Sortierung durch eine nicht vergleichsbasierte Sortierung wie die Radix-Sortierung ersetzen.
Das arithmetische Mittel einer Reihe von Winkeln stimmt möglicherweise nicht mit Ihrer intuitiven Vorstellung überein, wie hoch der Durchschnitt sein sollte. Zum Beispiel ist das arithmetische Mittel der Menge {179,179,0,181,181} 216 (und 144). Die Antwort, an die Sie sofort denken, ist wahrscheinlich 180, es ist jedoch bekannt, dass das arithmetische Mittel stark von Kantenwerten beeinflusst wird. Sie sollten sich auch daran erinnern, dass Winkel keine Vektoren sind, so ansprechend dies auch erscheinen mag, wenn Sie manchmal mit Winkeln arbeiten.
Dieser Algorithmus gilt natürlich auch für alle Größen, die der modularen Arithmetik (mit minimaler Anpassung) entsprechen, wie z. B. die Tageszeit.
Ich möchte auch betonen, dass, obwohl dies im Gegensatz zu den Vektorlösungen ein echter Durchschnitt der Winkel ist, dies nicht unbedingt bedeutet, dass es die Lösung ist, die Sie verwenden sollten, der Durchschnitt der entsprechenden Einheitsvektoren möglicherweise der Wert ist, den Sie tatsächlich haben sollte verwendet werden.
quelle
Sie müssen den Durchschnitt genauer definieren . Für den speziellen Fall von zwei Winkeln kann ich mir zwei verschiedene Szenarien vorstellen:
Ich sehe jedoch nicht, wie die zweite Alternative für den Fall von mehr als zwei Winkeln verallgemeinert werden kann.
quelle
Wie bei allen Durchschnittswerten hängt die Antwort von der Wahl der Metrik ab. Für eine gegebene Metrik M ist der Durchschnitt einiger Winkel a_k in [-pi, pi] für k in [1, N] der Winkel a_M, der die Summe der quadratischen Abstände d ^ 2_M (a_M, a_k) minimiert. Für einen gewichteten Mittelwert schließt man einfach die Gewichte w_k in die Summe ein (so dass sum_k w_k = 1). Das ist,
a_M = arg min_x sum_k w_k d ^ 2_M (x, a_k)
Zwei gängige Metrikoptionen sind die Frobenius- und die Riemann-Metrik. Für die Frobenius-Metrik existiert eine direkte Formel, die dem in der Kreisstatistik üblichen Begriff der durchschnittlichen Peilung entspricht. Weitere Informationen finden Sie unter "Mittelwerte und Mittelung in der Rotationsgruppe", Maher Moakher, SIAM Journal on Matrix Analysis and Applications, Band 24, Ausgabe 1, 2002.
http://link.aip.org/link/?SJMAEL/24/1/1
Hier ist eine Funktion für GNU Octave 3.2.4, die die Berechnung durchführt:
quelle
Ich möchte eine Methode, die ich verwendet habe, mit einem Mikrocontroller teilen, der keine Gleitkomma- oder Trigonometriefunktionen hatte. Ich musste immer noch 10 Rohlagerwerte "mitteln", um Abweichungen auszugleichen.
Es ist nicht ideal; es kann brechen. Ich bin in diesem Fall damit durchgekommen, weil sich das Gerät nur sehr langsam dreht. Ich werde es dort veröffentlichen, falls jemand anderes unter ähnlichen Einschränkungen arbeitet.
quelle
Auf Englisch:
In Python:
Ein #numpy NX1 Array von Winkeln
quelle
Hier ist die vollständige Lösung: (Die Eingabe ist eine Anordnung von Peilungen in Grad (0-360).
quelle
In Python mit Winkeln zwischen [-180, 180]
Einzelheiten:
Für den Durchschnitt von zwei Winkeln gibt es zwei Durchschnittswerte, die 180 ° voneinander entfernt sind, aber wir möchten vielleicht den näheren Durchschnitt.
Visuell ergibt der Durchschnitt von Blau ( b ) und Grün ( a ) den blaugrünen Punkt:
Winkel 'Wrap Around' (z. B. 355 + 10 = 5), aber Standardarithmetik ignoriert diesen Verzweigungspunkt. Wenn jedoch der Winkel b dem Verzweigungspunkt entgegengesetzt ist, ergibt ( b + g ) / 2 den nächsten Durchschnitt: den blaugrünen Punkt.
Für zwei beliebige Winkel können wir das Problem so drehen, dass einer der Winkel dem Verzweigungspunkt entgegengesetzt ist, eine Standardmittelung durchführen und dann zurückdrehen.
quelle
Ich würde den Vektorweg mit komplexen Zahlen gehen. Mein Beispiel ist Python, in das komplexe Zahlen integriert sind:
Beachten Sie, dass Python nicht brauchen eine temporäre neue Liste von Vektoren, die alle der oben in einem Schritt durchgeführt werden kann , bauen; Ich habe mich nur für diesen Weg entschieden, um den Pseudocode zu approximieren, der auch für andere Sprachen gilt.
quelle
Hier ist eine vollständige C ++ - Lösung:
Es nimmt die Winkel in Form eines Doppelvektors an und gibt den Durchschnitt einfach als Doppel zurück. Die Winkel müssen in Grad angegeben werden, und natürlich ist der Durchschnitt auch in Grad.
quelle
avgCos
ist der Durchschnitt der x-Komponenten undavgSin
ist der Durchschnitt der y-Komponenten. Die Parameter für die Arkustangensfunktion sindatan2( y, x )
. Sollte Ihr Code nicht stattdessen lauten:atan2( avgSin, avgCos )
??Basierend auf Alnitaks Antwort habe ich eine Java-Methode zur Berechnung des Durchschnitts mehrerer Winkel geschrieben:
Wenn Ihre Winkel im Bogenmaß sind:
Wenn Ihre Winkel in Grad sind:
quelle
Hier ist eine Idee: Erstellen Sie den Durchschnitt iterativ, indem Sie immer den Durchschnitt der Winkel berechnen, die am nächsten beieinander liegen, und dabei ein Gewicht beibehalten.
Eine andere Idee: Finden Sie die größte Lücke zwischen den angegebenen Winkeln. Suchen Sie den Punkt, der ihn halbiert, und wählen Sie dann den entgegengesetzten Punkt auf dem Kreis als Referenznullpunkt aus, um den Durchschnitt daraus zu berechnen.
quelle
Stellen wir diese Winkel mit Punkten auf dem Kreisumfang dar.
Können wir annehmen, dass alle diese Punkte auf dieselbe Hälfte des Kreises fallen? (Andernfalls gibt es keine offensichtliche Möglichkeit, den "Durchschnittswinkel" zu definieren. Stellen Sie sich zwei Punkte auf dem Durchmesser vor, z. B. 0 ° und 180 ° - ist der Durchschnitt 90 ° oder 270 °? Was passiert, wenn wir 3 oder mehr haben? Punkte gleichmäßig verteilen?)
Mit dieser Annahme wählen wir einen beliebigen Punkt auf diesem Halbkreis als "Ursprung" und messen den gegebenen Satz von Winkeln in Bezug auf diesen Ursprung (nennen wir dies den "relativen Winkel"). Beachten Sie, dass der relative Winkel einen absoluten Wert von weniger als 180 Grad hat. Nehmen Sie schließlich den Mittelwert dieser relativen Winkel, um den gewünschten Durchschnittswinkel zu erhalten (natürlich relativ zu unserem Ursprung).
quelle
Es gibt keine einzige "richtige Antwort". Ich empfehle, das Buch KV Mardia und PE Jupp, "Directional Statistics" (Wiley, 1999), für eine gründliche Analyse zu lesen.
quelle
(Ich möchte nur meinen Standpunkt aus der Schätzungstheorie oder der statistischen Inferenz teilen.)
Nimbles Versuch besteht darin, die MMSE ^ -Schätzung einer Reihe von Winkeln zu erhalten, aber es ist eine der Möglichkeiten, eine "gemittelte" Richtung zu finden. Man kann auch eine MMAE ^ -Schätzung oder eine andere Schätzung als "gemittelte" Richtung finden, und dies hängt von Ihrem metrischen quantifizierenden Richtungsfehler ab. oder allgemeiner in der Schätzungstheorie die Definition der Kostenfunktion.
^ MMSE / MMAE entspricht dem minimalen mittleren quadratischen / absoluten Fehler.
ackb sagte: "Der durchschnittliche Winkel phi_avg sollte die Eigenschaft haben, dass sum_i | phi_avg-phi_i | ^ 2 minimal wird ... sie mitteln etwas, aber keine Winkel."
---- Sie quantifizieren Fehler im quadratischen Sinne und es ist einer der häufigsten Wege, jedoch nicht der einzige. Die Antwort, die von den meisten Menschen hier bevorzugt wird (dh Summe der Einheitsvektoren und Ermittlung des Ergebniswinkels), ist tatsächlich eine der vernünftigen Lösungen. Es ist (kann bewiesen werden) der ML-Schätzer, der als die "gemittelte" Richtung dient, die wir wollen, wenn die Richtungen der Vektoren als von-Mises-Verteilung modelliert werden. Diese Verteilung ist nicht ausgefallen und nur eine periodisch abgetastete Verteilung von einem 2D-Guassianer. Siehe Gl. (2.179) in Bishops Buch "Mustererkennung und maschinelles Lernen". Auch hier ist es keineswegs die einzig beste, um die "durchschnittliche" Richtung darzustellen, aber es ist durchaus vernünftig, sowohl eine gute theoretische Begründung als auch eine einfache Implementierung zu haben.
Nimble sagte: "ackb hat Recht, dass diese vektorbasierten Lösungen nicht als echte Durchschnittswerte von Winkeln betrachtet werden können, sondern nur ein Durchschnitt der Gegenstücke zu Einheitsvektoren sind."
----das ist nicht wahr. Die "Einheitsvektor-Gegenstücke" enthüllen die Information über die Richtung eines Vektors. Der Winkel ist eine Größe ohne Berücksichtigung der Länge des Vektors, und der Einheitsvektor ist etwas mit zusätzlichen Informationen, dass die Länge 1 ist. Sie können Ihren "Einheits" -Vektor so definieren, dass er die Länge 2 hat, es spielt keine Rolle.
quelle
Hier ist eine vollständig arithmetische Lösung, bei der gleitende Durchschnitte verwendet werden und die Werte normalisiert werden. Es ist schnell und liefert korrekte Antworten, wenn sich alle Winkel auf einer Seite des Kreises befinden (innerhalb von 180 ° zueinander).
Es ist mathematisch äquivalent zum Addieren des Versatzes, der die Werte in den Bereich (0, 180) verschiebt, den Mittelwert berechnet und dann den Versatz subtrahiert.
Die Kommentare beschreiben, welchen Bereich ein bestimmter Wert zu einem bestimmten Zeitpunkt annehmen kann
quelle
Nun, ich bin sehr spät zur Party, dachte aber, ich würde meine 2 Cent hinzufügen, da ich keine endgültige Antwort finden konnte. Am Ende habe ich die folgende Java-Version der Mitsuta-Methode implementiert, die hoffentlich eine einfache und robuste Lösung bietet. Zumal die Standardabweichung sowohl eine Maßstreuung liefert als auch, wenn sd == 90, anzeigt, dass die Eingabewinkel zu einem mehrdeutigen Mittelwert führen.
EDIT: Eigentlich habe ich festgestellt, dass meine ursprüngliche Implementierung noch weiter vereinfacht werden kann, und zwar besorgniserregend einfach, wenn man die Konversation und Trigonometrie berücksichtigt, die in den anderen Antworten vor sich gehen.
... und für alle (Java) Geeks da draußen können Sie den obigen Ansatz verwenden, um den mittleren Winkel in einer Linie zu erhalten.
quelle
Alnitak hat die richtige Lösung. Die Lösung von Nick Fortescue ist funktional dieselbe.
Für den Sonderfall wo
(Summe (x_Komponente) = 0,0 && Summe (y_Komponente) = 0,0) // zB 2 Winkel von 10 und 190 Grad pro Stück.
Verwenden Sie 0,0 Grad als Summe
Rechnerisch müssen Sie diesen Fall testen, da atan2 (0., 0.) undefiniert ist und einen Fehler erzeugt.
quelle
Der durchschnittliche Winkel phi_avg sollte die Eigenschaft haben, dass sum_i | phi_avg-phi_i | ^ 2 minimal wird, wobei der Unterschied in [-Pi, Pi) liegen muss (weil er möglicherweise kürzer ist, um umgekehrt zu sein!). Dies wird leicht erreicht, indem alle Eingabewerte auf [0, 2Pi] normalisiert werden, ein laufender Durchschnitt phi_run beibehalten wird und die Normalisierung | phi_i-phi_run | gewählt wird zu [-Pi, Pi) (durch Addition oder Subtraktion von 2Pi). Die meisten der oben genannten Vorschläge machen etwas anderes, was nicht der Fall ist diese minimale Eigenschaft hat, dh sie mitteln etwas , aber keine Winkel.
quelle
Ich habe das Problem mit Hilfe der Antwort von @David_Hanak gelöst. Wie er sagt:
Also habe ich den Durchschnitt aller Winkel berechnet. Und dann erhöhen Sie alle Winkel, die kleiner als dieser sind, um 360. Berechnen Sie dann den Durchschnitt neu, indem Sie sie alle addieren und durch ihre Länge dividieren.
Funktioniert perfekt.
quelle
Python-Funktion:
quelle
Sie können diese Funktion in Matlab verwenden:
quelle
Eine Lösung und eine kleine Erklärung finden Sie unter folgendem Link für JEDE Programmiersprache: https://rosettacode.org/wiki/Averages/Mean_angle
Zum Beispiel C ++ - Lösung :
Ausgabe:
Oder Matlab-Lösung :
quelle
Während die Antwort von starblue den Winkel des durchschnittlichen Einheitsvektors angibt, ist es möglich, das Konzept des arithmetischen Mittels auf Winkel zu erweitern, wenn Sie akzeptieren, dass es möglicherweise mehr als eine Antwort im Bereich von 0 bis 2 * pi (oder 0 ° bis) gibt 360 °). Beispielsweise kann der Durchschnitt von 0 ° und 180 ° entweder 90 ° oder 270 ° betragen.
Das arithmetische Mittel hat die Eigenschaft, der Einzelwert mit der minimalen Summe der quadratischen Abstände zu den Eingabewerten zu sein. Der Abstand entlang des Einheitskreises zwischen zwei Einheitsvektoren kann leicht als inverser Kosinus ihres Punktprodukts berechnet werden. Wenn wir einen Einheitsvektor wählen, indem wir die Summe des quadratischen inversen Kosinus des Punktprodukts unseres Vektors und jedes Eingabeeinheitsvektors minimieren, haben wir einen äquivalenten Durchschnitt. Denken Sie auch hier daran, dass es in Ausnahmefällen zwei oder mehr Mindestwerte geben kann.
Dieses Konzept könnte auf eine beliebige Anzahl von Dimensionen erweitert werden, da der Abstand entlang der Einheitskugel genauso berechnet werden kann wie der Abstand entlang des Einheitskreises - der inverse Kosinus des Punktprodukts zweier Einheitsvektoren.
Für Kreise könnten wir diesen Durchschnitt auf verschiedene Arten lösen, aber ich schlage den folgenden O (n ^ 2) -Algorithmus vor (Winkel sind im Bogenmaß und ich vermeide die Berechnung der Einheitsvektoren):
Wenn alle Winkel innerhalb von 180 ° zueinander liegen, könnten wir einen einfacheren O (n) + O (Sortier) -Algorithmus verwenden (wiederum unter Verwendung des Bogenmaßes und unter Vermeidung der Verwendung von Einheitsvektoren):
Um Grad zu verwenden, ersetzen Sie pi einfach durch 180. Wenn Sie mehr Dimensionen verwenden möchten, müssen Sie höchstwahrscheinlich eine iterative Methode verwenden, um den Durchschnitt zu ermitteln.
quelle
Das Problem ist sehr einfach. 1. Stellen Sie sicher, dass alle Winkel zwischen -180 und 180 Grad liegen. 2. a Addiere alle nicht negativen Winkel, nimm ihren Durchschnitt und zähle, wie viele. 2. b. Füge alle negativen Winkel hinzu, nimm ihren Durchschnitt und zähle, wie viele. 3. Nehmen Sie die Differenz von pos_average minus neg_average. Wenn die Differenz größer als 180 ist, ändern Sie die Differenz in 360 minus Differenz. Ansonsten ändern Sie einfach das Vorzeichen der Differenz. Beachten Sie, dass der Unterschied immer nicht negativ ist. Der Average_Angle entspricht dem pos_average plus Differenz multipliziert mit dem "Gewicht", der negativen Anzahl geteilt durch die Summe aus negativer und positiver Anzahl
quelle
Hier ist ein Java-Code für durchschnittliche Winkel, ich denke, es ist ziemlich robust.
quelle
Ich habe eine andere Methode als @Starblue, die "richtige" Antworten auf einige der oben angegebenen Winkel gibt. Beispielsweise:
Es wird eine Summe über die Unterschiede zwischen aufeinanderfolgenden Winkeln verwendet. Der Code (in Matlab):
quelle
[-90,90,40]
und zurück[90,-90,40]
. Ich denke nicht, dass ein nicht kommutativer Durchschnitt sehr nützlich ist.