Averaging Angles

(Archive Question of the Week)

An interesting question that has been referred to many times since it was written in 1999 deals with averaging angles. At first the question seems trivial; then almost impossible; and then we end up with a rather simple formula that is totally unlike what we started with. And further applications lead to new issues that make it continue to interest us.

Angles don’t behave quite like numbers

Here is the question:

Averaging Two Angles

How do you take the average of two or more angles?

The average of 179, 180, and 181 is 180, but the average of 359, 0, and 1 is not 180.

Dave poses a seemingly simple question, but briefly states what troubles him about it. Averaging is averaging, right? The average of 179, 180, and 181 is obviously 180, and the calculation (if you need it at all) is easy: \(\frac{179 + 180 + 181}{3} = \frac{540}{3} = 180\). Unfortunately, because he mistyped his counterexample (possibly confusing it with the average of 359 and 1 alone), it took a little discussion before I saw his point. All I did initially was to show how to find the averages, so he could compare that to what he did:

Hi, Dave.

To find an average, or mean, of a set of numbers, you add up the numbers and then divide by the number of numbers you added. In your examples, there are three numbers, so you divide the sum by 3:

    179+180+181   540
    ----------- = --- = 180
         3         3

    359+0+1   360
    ------- = --- = 120
       3       3

He was right that the second answer wasn’t 180, but why was that important? It seems that he wrote 180 where he meant 120, and the problem he saw was that 120 didn’t make sense as the answer. He had to clarify:

Right, but that does NOT take the average of three ANGLES. The average of the three angles in the second example should be 0.

Ah! So if you have angles 359°, 0°, and 1° and draw them together, they are all 1 degree apart, just as 179°, 180°, and 181° are; but in the latter case averaging yields the angle you expect (the one in the middle), but in the former it doesn’t. I started to see the point:

I missed your point because you'd written 180 instead of 120.

I think it might be helpful if you gave me some context - why do you want the average? The meaning will be different in certain kinds of problems, depending for instance on whether you are looking at the angles as a turn through 359 degrees, or as a direction 359 degrees from north.

As you stated the question, I would still just average the numbers, as I did. If something turns, say, 359 degrees to the left in the first hour, stays stationary in the second hour, and turns 1 degree to the right in the third hour, then on average it has turned 120 degrees per hour. Presumably there is a reason for giving the angle as 359 rather than as -1 degree; in the latter case, of course, the average would be zero. In this sense, there is a difference between -1 and 359 degrees.

Angles can be thought of in several different ways. In geometry, we think of an angle as a mere figure composed of two rays, or as the (unsigned) “distance” between them. In trigonometry, we think of it as a rotation (clockwise or counterclockwise): a (signed) “motion”, so that different motions can result in the the same final geometrical configuration (coterminal angles). In navigation, we think of it as a direction (relative to north), and do not distinguish coterminal angles.

In terms of rotations, it makes perfectly good sense to average angles just as we average numbers. In the following picture, to make things more visible, I have changed the angles to 350°, 0°, and 10°; if we start at A, rotate clockwise 350° to B, then 0° (staying at B), then 10° to C, we have rotated a total of 360°, and on average we have rotated 120° per move.

If the first rotation were -10°, the total rotation (and therefore the average) would be 0°.

But Dave is not thinking in terms of rotations! He is thinking of locations on a circle, or directions, or something of that sort:

Here, we just have a point A at 350° from north (measuring angles as in headings in navigation), B at 0°, and C at 10°. Clearly, the average in this sense ought to be 0°. From this perspective, 350° is the same as -10°; signs and rotations are not the issue, just where you end up. So now I could start pondering the problem Dave had posed:

But you've raised an interesting question: if we think of the angles just as directions, then 359 and -1 should mean the same thing, and the average should not depend on how I state it. This is an inherent problem with angles, and this ambiguity shows up in other places, notably in working with complex numbers, where for example we divide an angle by 3 to find the cube root, and there are actually three answers 120 degrees apart, much as in this problem.

Let's look at your problem in terms of wind direction. Suppose the wind is blowing at a constant speed, but one day it blows from 359 degrees, the next from 0 degrees, and the next from 1 degree. What is the average wind direction? If the answer isn't 0 degrees, something's wrong.

Directions are best represented by vectors

Now I have a model for what Dave might intend to do with the average. (He never did tell me, though others later did state specific applications.)  Thinking about what it would mean to average directions, I decided that the most reasonable would be in terms of vectors: Add the n unit vectors representing each direction, and divide the resultant vector by n.

Here I have added vectors a, b, and c by putting them end to end, and the resultant vector, OE, clearly is in the direction of B as expected. (Dividing by 3 has no effect on the direction, so I don’t really need to do that for our purposes.)

I first explained with reference to the three directions in the question:

I would approach this in terms of vectors. The wind velocities can be represented by vectors

    V1 = (V cos(359), V sin(359)) = (0.99985V, -0.0175V)
    V2 = (V cos(0), V sin(0))     = (1, 0)
    V3 = (V cos(1), V sin(1))     = (0.99985V, 0.0175V)

Now if we add these vectors and divide by 3, we get

    (V1+V2+V3)/3 = (2.99970/3, 0) = (0.99990, 0)

and this vector has direction

    tan^-1(0) = 0 degrees

as expected. We can also see that because the wind turned, the average strength in this direction is a little less than 1. If you haven't seen vectors or trigonometry yet, this may suggest how valuable they are!

Dave wasn’t familiar with the notation \(\tan^{-1}(x)\), which is also called \(\arctan(x)\), the inverse tangent, but he was satisfied with the answer as meeting his needs.

Refining the formula

Four years later, another visitor, Larry, read this answer, and wrote to ask why he wasn’t getting the right answers. This happens fairly often!

I tried using the method you give; however, I get a close answer, but usually not an exact answer. For instance when I average 5 degrees and 15 degrees, the average should be 10 degrees, but instead I obtain 9.814 degrees.  I used the scientific calculator that comes with Windows Office Professional software, which is accurate to 33 places.   

Being almost 0.2 degrees off is significant as compared to the correct answer. Having a calculator that has tables correct to 33 places makes me believe that the answer should be more accurate than this. Maybe there is a problem with the tables in the calculator that I am using. If so, is there calculator that is more accurate?

The issue can’t be mere accuracy; he must be doing something wrong. I took the occasion to rewrite the formula without explicit reference to vectors, to make it easier for others, and then checked that these calculation gave the correct result:

The method given [on that page] can be put into a formula this way:

              sum of sines of angles
  A = arctan ------------------------
             sum of cosines of angles

For your example, we have

  sin(5) + sin(15)   0.08716+0.25882   0.34597
  ---------------- = --------------- = ------- = 0.17633
  cos(5) + cos(15)   0.99619+0.96593   1.96212

  A = arctan(0.17633) = 10

I presume you did something different; if you want help to see what you did wrong, please tell me how you tried to apply the method there. 

I should mention for completeness that the arctan (inverse tangent) always gives an answer between -90 and +90 degrees, so if the angles you are working with are outside that range, you will have to adjust, by finding the angle in the correct quadrant that has the indicated tangent.

I don’t know what he did to get his wrong answer; he never responded. I tried doing the calculations with my calculator in radian mode (the usual culprit in this sort of formula), and got an answer of 0.575 radians (32.9°). This may look wrong, but in fact, if we add 3π to 0.575, we get 10 radians, showing that this answer is coterminal with the expected average. (In radians, 10 and 15 are rather large, outside of the usual range.) But this is not what Dave got. Nothing else I tried gave 9.814°. So this is a mystery. (Let me know if you figure it out.)

A couple months later, though, another visitor, Stephen, wrote to say

If you're writing a program or spreadsheet to do this, atan2 is a better choice than atan, as it gets the signs correct automatically.

This was a helpful suggestion for anyone programming this formula. Computer languages commonly provide this special function that takes x and y coordinates and finds the angle to that point directly, rather than through \(\arctan\left(\frac{y}{x}\right)\), which as I had mentioned doesn’t always get the quadrant right. So I wrote up a final version of the formula:

Hi, Stephen.

That's true, though the person who wrote was using a calculator.

If you were using a programming language or spreadsheet program that supports the "atan2" function, for which

   atan2(x,y) = arctan(y/x)

with the appropriate sign according to the quadrant of the coordinates, then a better formula would be

   A = atan2(sum of cosines, sum of sines)

Be careful, however: the definition above is for Excel; in C++, it's atan2(y, x), with the order of arguments reversed. The function is not quite standard everywhere.

For more about arctan and atan2, see:

   Arctan and Polar Coordinates 
   http://mathforum.org/library/drmath/view/54114.html

This last link demonstrates how to get the right quadrant if you don’t have atan2, and then briefly mentions the function.  It should also be mentioned that in any programming language these functions [almost] always work with radians rather than degrees.

Among others who later wrote to us about this (and went unarchived for one reason or another), a couple were looking for a way to average wind directions, and one wanted to average the direction of a plane (in order to ignore small deviations from course and record the overall direction). The latter, I felt, really should just average angles as numbers, with some adjustment when crossing from 1 to 359. The former probably did need the vector method, but needed to recognize that there can be cases where the average (of 0° and 180°, for example) is undefined, because the vector sum is 0, which has no direction.

Bottom line: if you want to average directions specified as angles (such as headings or bearings), in Excel, you can use this formula: A = atan2(sum_of_cosines, sum_of_sines).

Addendum: many angles, small angles

One of these later writers, Nick, wrote in late 2003 (unarchived),

In http://mathforum.org/library/drmath/view/53924.html you discuss two methods for averaging angles. The first method is to calculate a simple arithmetic average, eg:

(5 + 15) / 2 = 10

[You need a special rule so that, eg, the average of 1 and 359 is (1 + -1) / 2 = 0. That's OK.]

The second method is to treat the angles as vectors, eg:

atan (sin (5) + sin (15) / cos (5) + cos (15)) = 10

So, for two angles, the two methods seem to be equivalent.

Interestingly, for more than three angles the two methods seem to result in similar, but not identical results. So, for example, if we want to average 5, 13 and 15 the first approach gives 11, the second approach gives 11.00244215 (using Excel, or the windows calculator).

This difference seems too large to be just a numerical artifact, so I am curious as to how to interpret the two different results!

I replied,

This doesn't surprise me much; it just reflects the difference between linear and circular geometry. I would expect the two to be different.

As I explained, different ways of averaging are appropriate in different contexts. Thinking of the angles as directions, you want to use the vector approach. Here you are working in a fully two-dimensional setting, and want to add the directions as vectors. But if you are just thinking of, say, angles as positions on a circle, you are using the circle as if it were merely a curved ruler, and they will add like ordinary numbers.

I played with this a bit and found that the difference between the two methods increases when the angles are less symmetrical, like 0, 80, and 90 as opposed to 0, 45, and 90. With two angles, you are always symmetrical, and both methods will give the same answer. Try drawing the vector addition graphically, and you will get a sense of why there is a difference.

He replied,

You make an interesting observation that the results diverge as the angles become less "symmetrical". Further experimentation shows that the results are essentially identical if the differences between the angles are small - eg 20.0, 20.1 and 20.5 give the same result by either method.

A colleague suggested that the fact that the sine of a small angle is approximately equal to the angle itself is somehow involved. Perhaps I should attempt a proof that the two methods are equivalent in this case (although my trigonometry is not that great).

Anyway, the context in which I was interested is in surveying, in which you may wish to repeatedly measure an angle subtended by three points, and calculate the mean and standard deviation. In this case, the angles to be meaned have a range of only a few seconds, and so the two approaches would seem to be equivalent.

My response:

The comment about the sine is exactly what was in my mind, though it's hard to express it clearly. It is this similarity and difference -- that the sine, or chord, is very close to the angle, or arc, but not quite -- that is behind the subtleties of trisecting an angle; people often think they have found a way to do it, but they are really trisecting a chord, or something like that, so that it is very close for some cases but not for others. Something like that is happening here.

Certainly your observation with small differences between angles is true: in the limit, both methods will be equivalent. And I think you are right that you can use either method in your situation. You could probably analyze the situation more closely and might find a third method that better fits what you are doing, but it wouldn't be worth the effort!

It’s always interesting to see what others do with the ideas we put out there.

11 thoughts on “Averaging Angles”

  1. I’m wondering if the discrepancies are due to the fact that inverse tan is a non-linear function, and the expectation of a NL function applied to x is generally not equal to the function applied to the expectation of x. That is, E(g(x)) != g(E(x)) in general, and I would say certainly not true for g(x) = arctan(x).

    1. That is at least related to the issue discussed at the end of the post; as I said, “It just reflects the difference between linear and circular geometry. I would expect the two to be different” – that is, linear vs. non-linear. Of course, what you say isn’t quite literally applicable, as my formula does not involve the mean of tangents, but something similar.

  2. This question is probably already sufficient answered but her is my 2 bits. Averaging unit vectors is not the same thing as averaging angles. Look at the example of (0, 0, 90) degrees. A straight mean would be 30. The vector average is 26.565… The method you want to use depends what you are trying to do. I got interested in this problem because I wanted to average together wind reading which are vector quantities. If you are averaging together the angle measurements from several different readings you would want to do a straight average but of course you need to watch out for the wrap around at 360 degrees.

    1. Yes, this is essentially a brief summary of my last section, Addendum, where I said, “As I explained, different ways of averaging are appropriate in different contexts.” In particular, your example is highly asymmetrical, with two vectors in the same direction. What’s nice about it is that it is very easy to see: The three vectors, end to end, form a right triangle with legs 2 and 1, so the angle is arctan(1/2) = 26.565 deg as you say. The numerical average, 30 degrees, represents a right triangle with leg 1 and hypotenuse 2.

  3. The problem I found was when the circular quantities ranged between 0-180, or when you want to do state fusion using a covariance matrix, a different approach for weighted averaging was necessary.

    Seems like you could test for proximity first. for example if -1 is closer to 0 and 1 than 359, then simply do an arithmetic mean between -1 0 and 1. You can always do a mod to loop it between 0-360. This would allow for state fusion with covariance matrix.

  4. Average of 2 angles (in degrees):

    function avgAng(a1,a2){
    var minA=Math.min(a1,a2),
    maxA=Math.max(a1,a2),
    d1=maxA-minA,
    d2=(minA+360)-maxA,
    avgA=(d1<d2?minA+(d1/2):maxA+(d2/2));
    return avgA+(avgA=360?-360:0));
    }

    1. This covers only the easy case with two angles; almost everything in the post is about more than two.

      In this case, the “average” you expect will be either the ordinary average, (a1+a2)/2, or 180 more or less than that (whichever is in the right range, and within 90 degrees of both given angles). So the code could be a little simpler.

      Moreover, your code sometimes returns an angle greater than 360! For example, if a1=100 and a2=350, then d1=250, d2=110, and avgA=350+110/2=405. On the other hand, the naïve average is 225, and subtracting 180 gives 45, which makes sense.

      This is a tricky thing to code for all cases, even when you restrict it to two angles!

  5. Mauricio Girardi Schappo

    I was facing this problem in my research (angles as directions). Thinking of angles as unit vectors is really clever.

    Instead, what I came up with was to average the cosine of angles, = (cos(theta1) + cos(theta2) + …)/N, and then taking the arccos(). I never really gave it much thought, but this way it feels more natural, because cos(theta) is a continuous function defined for all reals, making the average well-defined and single-valued (whatever range of theta you have — I think, though never proved)…

    Namely: cos(x) = 1 – x² + … for small angles |x|, so averaging 359 deg with 0 and 1,
    acos((cos(1*pi/180)+cos(0)+cos(359*pi/180))/3)*180/pi = 0.8 degrees
    which is almost zero (better than 120 degrees).
    The same works at the other side, at 180 degrees:
    acos((cos(pi)+cos(pi-pi/180)+cos(pi+pi/180))/3)*180/pi = 179.2 degrees

    The difference to the real value of the average angle decreases as the number of samples increase:
    if you consider 1000 angles from -1 degree to 1 degree, and average the cosine, and then take the arccos, you get 0.5 deg… In MATLAB:
    acos(mean(cos(linspace(-1,1,1000).*pi/180)))*180/pi = 0.5 degrees

    Two caveats: the 0.5 degrees accuracy seems to be a “fixed point” (larger and larger N converge to this error, and it can be smaller than this — I tested it numerically)… The second is that we must take care that is always bounded in -1 to 1.

    1. One problem with this approach is that, since the cosine is an even function, you are losing the sign of the angle — it’s as if you were averaging, not the angles themselves, but their absolute values. So if you “average” the angles +1 and -1 degree, your answer will be 1 degree, not 0 degrees.

      This explains your 0.5 degree limit; if your numbers are equally spaced from -1 to +1 degree, you are really “averaging” angles from 0 to 1 degree, so half a degree sounds about right. You are, to be more precise, finding the center of mass of the arc between those angles, and taking the inverse cosine of that, which I find to be 0.577 degrees, if my calculation is correct.

      Your average might make a little sense if the angles are all positive; but it would depend, as I have said, on what you are using it for.

  6. I am very confused as I tried to implement your method and obtained way off results.
    For instance, using your method to average these angles: [22.98, 35.04, 48., 39.84, 44.10, 66.41, 22.98] returned me the value of 80.28 degrees, which is way off. Maybe this had to do with the fact that I had to convert angles to radians before computing the sinuses and cosinuses ( I am working with Python). After struggling a long time with different way of implementing it, I resorted to use ChatGPT, which averages the cosinues and sinuses instead of summing them, which was very surprising as I did not expect that to make a difference. It gave me the answer of 39.84 degrees, which made much more sense visually when I looked at my data. Do you have any idea where this issue might come from ? Thank you very much for what you are doing.

    1. I can’t tell what you did wrong; I get 39.84 degrees by my method, and averaging should give exactly the same result as summing. There must be some error in your calculations using my method.

      I did it in a spreadsheet, which includes converting to and from radians:

      angle sin cos
      22.98 0.390409788 0.920641188
      35.04 0.574148173 0.818751413
      48 0.743144825 0.669130606
      39.84 0.640645907 0.767836456
      44.1 0.695912797 0.718126298
      66.41 0.91643259 0.400189091
      22.98 0.390409788 0.920641188
      sum 4.351103867 5.21531624
      sin/cos 0.83429339
      atan 39.83801904

Leave a Reply to Dave Peterson Cancel Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.