Je veux calculer la moyenne d'un ensemble de données circulaires. Par exemple, je pourrais avoir plusieurs échantillons de la lecture d'une boussole. Le problème, bien sûr, est de savoir comment gérer le bouclage. Le même algorithme peut être utile pour une horloge.
La vraie question est plus compliquée - que signifient les statistiques sur une sphère ou dans un espace algébrique qui "s'enroule", par exemple le groupe additif mod n. La réponse n'est peut-être pas unique, par exemple, la moyenne de 359 degrés et 1 degré pourrait être de 0 degrés ou 180, mais statistiquement 0 semble mieux.
C'est un vrai problème de programmation pour moi et j'essaie de faire en sorte que cela ne ressemble pas à un problème mathématique.
Réponses:
Calculez les vecteurs unitaires à partir des angles et prenez l'angle de leur moyenne.
la source
Cette question est examinée en détail dans le livre: "Statistics On Spheres", Geoffrey S. Watson, University of Arkansas Lecture Notes in the Mathematical Sciences, 1983 John Wiley & Sons, Inc. comme mentionné sur http: //catless.ncl. ac.uk/Risks/7.44.html#subj4 par Bruce Karsh.
Un bon moyen d'estimer un angle moyen, A, à partir d'un ensemble de mesures d'angle a [i] 0 <= i
La méthode donnée par starblue est équivalente en calcul, mais ses raisons sont plus claires et probablement plus efficaces par programme, et fonctionnent également bien dans le cas zéro, alors bravo à lui.
Le sujet est maintenant exploré plus en détail sur Wikipédia , et avec d'autres utilisations, comme les parties fractionnaires.
la source
Je vois le problème - par exemple, si vous avez un angle de 45 pieds et un angle de 315 pieds, la moyenne "naturelle" serait de 180 pieds, mais la valeur que vous voulez est en fait de 0 pieds.
Je pense que Starblue est sur quelque chose. Calculez simplement les coordonnées cartésiennes (x, y) pour chaque angle et ajoutez les vecteurs résultants ensemble. Le décalage angulaire du vecteur final doit être le résultat souhaité.
J'ignore pour l'instant qu'un cap de boussole commence au nord et va dans le sens des aiguilles d'une montre, alors que les coordonnées cartésiennes "normales" commencent par zéro le long de l'axe X, puis vont dans le sens inverse des aiguilles d'une montre. Les maths devraient fonctionner de la même manière quoi qu'il en soit.
la source
cos()
,sin()
etatan2()
donner des approximations (bons, mais toujours au large par 1 ou 2 ulps) donc plus vous en moyenne, plus les erreurs que vous comprennent.POUR LE CAS PARTICULIER DES DEUX ANGLES:
La réponse ((a + b) mod 360) / 2 est FAUX . Pour les angles 350 et 2, le point le plus proche est 356 et non 176.
Le vecteur unitaire et les solutions trigonométriques peuvent être trop chers.
Ce que j'ai obtenu d'un peu de bricolage, c'est:
la source
ackb a raison de dire que ces solutions vectorielles ne peuvent pas être considérées comme de vraies moyennes d'angles, elles ne sont qu'une moyenne des homologues des vecteurs unitaires. Cependant, la solution suggérée par ackb ne semble pas mathématiquement valable.
Ce qui suit est une solution dérivée mathématiquement de l'objectif de minimisation (angle [i] - avgAngle) ^ 2 (où la différence est corrigée si nécessaire), ce qui en fait une véritable moyenne arithmétique des angles.
Tout d'abord, nous devons regarder exactement dans quels cas la différence entre les angles est différente de la différence entre leurs homologues en nombre normal. Considérons les angles x et y, si y> = x - 180 et y <= x + 180, alors nous pouvons utiliser la différence (xy) directement. Sinon, si la première condition n'est pas remplie, nous devons utiliser (y + 360) dans le calcul au lieu de y. En conséquence, si la deuxième condition n'est pas remplie, nous devons utiliser (y-360) au lieu de y. Puisque l'équation de la courbe que nous minimisons les changements seulement aux points où ces inégalités changent de vrai à faux ou vice versa, nous pouvons séparer la gamme complète [0,360) en un ensemble de segments, séparés par ces points. Ensuite, il suffit de trouver le minimum de chacun de ces segments, puis le minimum du minimum de chaque segment, qui est la moyenne.
Voici une image montrant où les problèmes se produisent dans le calcul des différences d'angle. Si x se trouve dans la zone grise, il y aura un problème.
Pour minimiser une variable, en fonction de la courbe, nous pouvons prendre la dérivée de ce que nous voulons minimiser puis nous trouvons le point de retournement (qui est où la dérivée = 0).
Ici, nous appliquerons l'idée de minimiser la différence au carré pour dériver la formule de moyenne arithmétique commune: sum (a [i]) / n. La courbe y = sum ((a [i] -x) ^ 2) peut être minimisée de cette manière:
Maintenant, appliquez-le aux courbes avec nos différences ajustées:
b = sous-ensemble de a où la différence (angulaire) correcte a [i] -xc = sous-ensemble de a où la différence (angulaire) correcte (a [i] -360) -x cn = taille de cd = sous-ensemble de a où le différence (angulaire) correcte (a [i] +360) -x dn = taille de d
Cela seul n'est pas tout à fait suffisant pour obtenir le minimum, alors que cela fonctionne pour des valeurs normales, qui ont un ensemble illimité, donc le résultat se situera certainement dans la plage de l'ensemble et est donc valide. Nous avons besoin du minimum dans une plage (définie par le segment). Si le minimum est inférieur à la borne inférieure de notre segment, alors le minimum de ce segment doit être à la borne inférieure (car les courbes quadratiques n'ont qu'un seul point de retournement) et si le minimum est supérieur à la borne supérieure de notre segment, alors le minimum du segment est au limite supérieure. Une fois que nous avons le minimum pour chaque segment, nous trouvons simplement celui qui a la valeur la plus basse pour ce que nous minimisons (sum ((b [i] -x) ^ 2) + sum (((c [i] -360 ) -b) ^ 2) + somme (((d [i] +360) -c) ^ 2)).
Voici une image de la courbe, qui montre comment elle change aux points où x = (a [i] +180)% 360. L'ensemble de données en question est {65,92,230,320,250}.
Voici une implémentation de l'algorithme en Java, avec quelques optimisations, sa complexité est O (nlogn). Il peut être réduit à O (n) si vous remplacez le tri basé sur la comparaison par un tri non basé sur la comparaison, tel que le tri par base.
La moyenne arithmétique d'un ensemble d'angles peut ne pas correspondre à votre idée intuitive de ce que devrait être la moyenne. Par exemple, la moyenne arithmétique de l'ensemble {179,179,0,181,181} est 216 (et 144). La réponse à laquelle vous pensez immédiatement est probablement 180, mais il est bien connu que la moyenne arithmétique est fortement affectée par les valeurs de bord. Vous devez également vous rappeler que les angles ne sont pas des vecteurs, aussi attrayants que cela puisse paraître lorsqu'il s'agit parfois d'angles.
Cet algorithme s'applique bien entendu également à toutes les grandeurs qui obéissent à l'arithmétique modulaire (avec un ajustement minimal), comme l'heure de la journée.
Je voudrais également souligner que même s'il s'agit d'une vraie moyenne d'angles, contrairement aux solutions vectorielles, cela ne signifie pas nécessairement que c'est la solution que vous devriez utiliser, la moyenne des vecteurs unitaires correspondants peut bien être la valeur que vous devrait utiliser.
la source
Vous devez définir la moyenne plus précisément. Pour le cas spécifique de deux angles, je peux penser à deux scénarios différents:
Je ne vois pas comment la deuxième alternative peut être généralisée pour le cas de plus de deux angles, cependant.
la source
Comme toutes les moyennes, la réponse dépend du choix de la métrique. Pour une métrique M donnée, la moyenne de quelques angles a_k dans [-pi, pi] pour k dans [1, N] est cet angle a_M qui minimise la somme des carrés des distances d ^ 2_M (a_M, a_k). Pour une moyenne pondérée, on inclut simplement dans la somme les poids w_k (tels que sum_k w_k = 1). C'est,
a_M = arg min_x somme_k w_k d ^ 2_M (x, a_k)
Deux choix courants de métrique sont les métriques de Frobenius et de Riemann. Pour la métrique de Frobenius, il existe une formule directe qui correspond à la notion habituelle de relèvement moyen en statistique circulaire. Voir «Moyennes et moyennes dans le groupe de rotations», Maher Moakher, SIAM Journal on Matrix Analysis and Applications, volume 24, numéro 1, 2002, pour plus de détails.
http://link.aip.org/link/?SJMAEL/24/1/1
Voici une fonction pour GNU Octave 3.2.4 qui effectue le calcul:
la source
J'aimerais partager une méthode que j'ai utilisée avec un microcontrôleur qui n'avait pas de capacités de virgule flottante ou de trigonométrie. J'avais encore besoin de "faire la moyenne" de 10 lectures brutes de roulement afin de lisser les variations.
Ce n'est pas idéal; ça peut casser. Je m'en suis tiré dans ce cas car l'appareil ne tourne que très lentement. Je vais le mettre là-bas au cas où quelqu'un d'autre se retrouverait à travailler sous des restrictions similaires.
la source
En anglais:
En python:
Un tableau d'angles #numpy NX1
la source
Voici la solution complète: (l'entrée est un tableau de relèvement en degrés (0-360)
la source
En python, avec des angles compris entre [-180, 180)
Détails:
Pour la moyenne de deux angles, il y a deux moyennes distantes de 180 °, mais nous pouvons souhaiter la moyenne la plus proche.
Visuellement, la moyenne du bleu ( b ) et du vert ( a ) donne le point sarcelle:
Les angles «s'enroulent» (par exemple 355 + 10 = 5), mais l'arithmétique standard ignorera ce point de branchement. Cependant, si l'angle b est opposé au point de branchement, alors ( b + g ) / 2 donne la moyenne la plus proche: le point sarcelle.
Pour deux angles quelconques, nous pouvons faire pivoter le problème afin que l'un des angles soit opposé au point de branchement, effectuer un moyennage standard, puis effectuer une rotation arrière.
la source
J'irais la voie vectorielle en utilisant des nombres complexes. Mon exemple est en Python, qui a des nombres complexes intégrés:
Notez que Python n'a pas besoin de créer une nouvelle liste temporaire de vecteurs, tout ce qui précède peut être fait en une seule étape; J'ai juste choisi cette façon d'approximer le pseudo-code applicable à d'autres langues également.
la source
Voici une solution C ++ complète:
Il prend les angles sous la forme d'un vecteur de doubles, et renvoie la moyenne simplement comme un double. Les angles doivent être en degrés, et bien sûr la moyenne est également en degrés.
la source
avgCos
est la moyenne des x composantes etavgSin
est la moyenne des y composantes. Les paramètres de la fonction arc tangente sontatan2( y, x )
. Donc, votre code ne devrait-il pas être:atan2( avgSin, avgCos )
??Sur la base de la réponse d'Alnitak , j'ai écrit une méthode Java pour calculer la moyenne de plusieurs angles:
Si vos angles sont en radians:
Si vos angles sont en degrés:
la source
Voici une idée: construire la moyenne de manière itérative en calculant toujours la moyenne des angles les plus proches, en gardant un poids.
Autre idée: trouver le plus grand écart entre les angles donnés. Trouvez le point qui le coupe en deux, puis choisissez le point opposé sur le cercle comme zéro de référence pour calculer la moyenne.
la source
Représentons ces angles avec des points sur la circonférence du cercle.
Peut-on supposer que tous ces points tombent sur la même moitié du cercle? (Sinon, il n'y a pas de moyen évident de définir "l'angle moyen". Pensez à deux points sur le diamètre, par exemple 0 degré et 180 degrés --- est-ce que la moyenne est de 90 degrés ou 270 degrés? Que se passe-t-il lorsque nous avons 3 ou plus répartir uniformément les points?)
Avec cette hypothèse, nous choisissons un point arbitraire sur ce demi-cercle comme «origine», et mesurons l'ensemble donné d'angles par rapport à cette origine (appelons cela «l'angle relatif»). Notez que l'angle relatif a une valeur absolue strictement inférieure à 180 degrés. Enfin, prenez la moyenne de ces angles relatifs pour obtenir l'angle moyen souhaité (par rapport à notre origine bien sûr).
la source
Il n'y a pas une seule «bonne réponse». Je recommande de lire le livre, KV Mardia et PE Jupp, "Directional Statistics", (Wiley, 1999), pour une analyse approfondie.
la source
(Je veux juste partager mon point de vue de la théorie de l'estimation ou de l'inférence statistique)
L'essai de Nimble est d'obtenir l'estimation MMSE ^ d'un ensemble d'angles, mais c'est l'un des choix pour trouver une direction "moyennée"; on peut également trouver une estimation MMAE ^, ou une autre estimation comme étant la direction "moyennée", et cela dépend de votre erreur de quantification métrique de direction; ou plus généralement dans la théorie de l'estimation, la définition de la fonction de coût.
^ MMSE / MMAE correspond à l'erreur quadratique / absolue moyenne minimale.
ackb a dit "L'angle moyen phi_avg devrait avoir la propriété que sum_i | phi_avg-phi_i | ^ 2 devient minimal ... ils font la moyenne de quelque chose, mais pas des angles"
---- vous quantifiez les erreurs au sens carré moyen et c'est l'un des moyens les plus courants, mais pas le seul. La réponse favorisée par la plupart des gens ici (c'est-à-dire la somme des vecteurs unitaires et obtenir l'angle du résultat) est en fait l'une des solutions raisonnables. C'est (peut être prouvé) l'estimateur ML qui sert de direction «moyennée» que nous voulons, si les directions des vecteurs sont modélisées comme une distribution de von Mises. Cette distribution n'est pas fantaisiste, et n'est qu'une distribution périodiquement échantillonnée à partir d'un Guassien 2D. Voir Eqn. (2.179) dans le livre de Bishop's "Pattern Recognition and Machine Learning". Encore une fois, ce n'est en aucun cas le seul meilleur pour représenter la direction «moyenne», cependant, il est tout à fait raisonnable qui a à la fois une bonne justification théorique et une mise en œuvre simple.
Nimble a déclaré que "ackb a raison de dire que ces solutions vectorielles ne peuvent pas être considérées comme de vraies moyennes d'angles, elles ne sont qu'une moyenne des homologues des vecteurs unitaires"
----ce n'est pas vrai. Les "homologues de vecteur unitaire" révèlent les informations de la direction d'un vecteur. L'angle est une quantité sans tenir compte de la longueur du vecteur, et le vecteur unitaire est quelque chose avec des informations supplémentaires que la longueur est 1. Vous pouvez définir votre vecteur "unité" comme étant de longueur 2, cela n'a pas vraiment d'importance.
la source
Voici une solution entièrement arithmétique utilisant des moyennes mobiles et prenant soin de normaliser les valeurs. Il est rapide et fournit des réponses correctes si tous les angles sont d'un côté du cercle (à moins de 180 ° les uns des autres).
C'est mathématiquement équivalent à ajouter le décalage qui décale les valeurs dans la plage (0, 180), en calculant la moyenne puis en soustrayant le décalage.
Les commentaires décrivent la plage qu'une valeur spécifique peut prendre à un moment donné
la source
Eh bien, je suis extrêmement en retard à la fête, mais j'ai pensé ajouter mes 2 cents car je ne pouvais pas vraiment trouver de réponse définitive. Au final, j'ai implémenté la version Java suivante de la méthode Mitsuta qui, je l'espère, fournit une solution simple et robuste. D'autant plus que l'écart type fournit à la fois une dispersion de mesure et, si sd == 90, indique que les angles d'entrée donnent une moyenne ambiguë.
EDIT: En fait, j'ai réalisé que ma mise en œuvre originale peut être encore plus simplifiée, en fait d'une simplicité inquiétante compte tenu de toute la conversation et de la trigonométrie en cours dans les autres réponses.
... et pour tous les geeks (Java), vous pouvez utiliser l'approche ci-dessus pour obtenir l'angle moyen sur une ligne.
la source
Alnitak a la bonne solution. La solution de Nick Fortescue est fonctionnellement la même.
Pour le cas particulier où
(sum (x_component) = 0.0 && sum (y_component) = 0.0) // par exemple 2 angles de 10. et 190. degrés ea.
utiliser 0,0 degré comme somme
Sur le plan informatique, vous devez tester ce cas car atan2 (0., 0.) n'est pas défini et générera une erreur.
la source
L'angle moyen phi_avg devrait avoir la propriété que sum_i | phi_avg-phi_i | ^ 2 devient minime, où la différence doit être dans [-Pi, Pi) (car il peut être plus court d'aller dans l'autre sens!). Ceci est facilement réalisé en normalisant toutes les valeurs d'entrée à [0, 2Pi), en conservant une moyenne courante de phi_run et en choisissant de normaliser | phi_i-phi_run | à [-Pi, Pi) (en ajoutant ou soustractine 2Pi). La plupart des suggestions ci-dessus font autre chose qui n'a pas cette propriété minimale, c'est-à-dire qu'elles font la moyenne de quelque chose , mais pas des angles.
la source
J'ai résolu le problème à l'aide de la réponse de @David_Hanak. Comme il le déclare:
J'ai donc calculé la moyenne de tous les angles. Et puis tous les angles inférieurs à cela, augmentez-les de 360. Puis recalculez la moyenne en les additionnant tous et en les divisant par leur longueur.
Fonctionne parfaitement.
la source
Fonction Python:
la source
Vous pouvez utiliser cette fonction dans Matlab:
la source
Vous pouvez voir une solution et une petite explication dans le lien suivant, pour TOUT langage de programmation: https://rosettacode.org/wiki/Averages/Mean_angle
Par exemple, solution C ++ :
Production:
Ou solution Matlab :
la source
Alors que la réponse de starblue donne l'angle du vecteur unitaire moyen, il est possible d'étendre le concept de la moyenne arithmétique aux angles si vous acceptez qu'il peut y avoir plus d'une réponse dans la plage de 0 à 2 * pi (ou de 0 ° à 360 °). Par exemple, la moyenne de 0 ° et 180 ° peut être de 90 ° ou 270 °.
La moyenne arithmétique a la propriété d'être la valeur unique avec la somme minimale des carrés des distances aux valeurs d'entrée. La distance le long du cercle unitaire entre deux vecteurs unitaires peut être facilement calculée comme le cosinus inverse de leur produit scalaire. Si nous choisissons un vecteur unitaire en minimisant la somme du cosinus inverse carré du produit scalaire de notre vecteur et de chaque vecteur unitaire d'entrée, nous avons une moyenne équivalente. Encore une fois, gardez à l'esprit qu'il peut y avoir deux minimums ou plus dans des cas exceptionnels.
Ce concept pourrait être étendu à n'importe quel nombre de dimensions, car la distance le long de la sphère unitaire peut être calculée exactement de la même manière que la distance le long du cercle unitaire - le cosinus inverse du produit scalaire de deux vecteurs unitaires.
Pour les cercles, nous pourrions résoudre cette moyenne de plusieurs façons, mais je propose l'algorithme O (n ^ 2) suivant (les angles sont en radians, et j'évite de calculer les vecteurs unitaires):
Si tous les angles sont à moins de 180 ° les uns des autres, alors nous pourrions utiliser un algorithme O (n) + O (tri) plus simple (à nouveau en utilisant des radians et en évitant d'utiliser des vecteurs unitaires):
Pour utiliser les degrés, remplacez simplement pi par 180. Si vous prévoyez d'utiliser plus de dimensions, vous devrez probablement utiliser une méthode itérative pour résoudre la moyenne.
la source
Le problème est extrêmement simple. 1. Assurez-vous que tous les angles sont compris entre -180 et 180 degrés. 2. a Additionnez tous les angles non négatifs, prenez leur moyenne et COMPTEZ combien 2. b.Ajoutez tous les angles négatifs, prenez leur moyenne et COMPTEZ combien. 3. Prenez la différence de pos_average moins neg_average Si la différence est supérieure à 180, changez la différence en 360 moins la différence. Sinon, changez simplement le signe de la différence. Notez que la différence est toujours non négative. Le Average_Angle est égal à pos_average plus la différence multipliée par le "poids", le nombre négatif divisé par la somme des nombres négatifs et positifs
la source
Voici du code java aux angles moyens, je pense que c'est raisonnablement robuste.
la source
J'ai une méthode différente de @Starblue qui donne des réponses «correctes» à certains des angles donnés ci-dessus. Par exemple:
Il utilise une somme sur les différences entre les angles consécutifs. Le code (dans Matlab):
la source
[-90,90,40]
et[90,-90,40]
; Je ne pense pas qu'une moyenne non commutative soit très utile.