Averaging angles... Again

Viewed 9612

I want to calculate the average of a set of angles, which represents source bearing (0 to 360 deg) - (similar to wind-direction)

I know it has been discussed before (several times). The accepted answer was Compute unit vectors from the angles and take the angle of their average.

However this answer defines the average in a non intuitive way. The average of 0, 0 and 90 will be atan( (sin(0)+sin(0)+sin(90)) / (cos(0)+cos(0)+cos(90)) ) = atan(1/2)= 26.56 deg

I would expect the average of 0, 0 and 90 to be 30 degrees.

So I think it is fair to ask the question again: How would you calculate the average, so such examples will give the intuitive expected answer.

Edit 2014:

After asking this question, I've posted an article on CodeProject which offers a thorough analysis. The article examines the following reference problems:

  • Given time-of-day [00:00-24:00) for each birth occurred in US in the year 2000 - Calculate the mean birth time-of-day
  • Given a multiset of direction measurements from a stationary transmitter to a stationary receiver, using a measurement technique with a wrapped normal distributed error – Estimate the direction.
  • Given a multiset of azimuth estimates between two points, made by “ordinary” humans (assuming to subject to a wrapped truncated normal distributed error) – Estimate the direction.
13 Answers

You are correct that the accepted answer of using traditional average is wrong.

An average of a set of points x_1 ... x_n in a metric space X is an element x in X that minimizes the sum of distances squares to each point (See Frechet mean). If you try to find this minimum using simple calculus with regular real numbers, you will recover the standard "add up and divide by n" formula.

For an angle, our elements are actually points on the unit circle S1. Our metric isn't euclidean distance, but arc length, which is proportional to angle.

So, the average angle is the one that minimizes the square of the angle difference between each other angle. In other words, if you have a function angleBetween(a, b) you want to find the angle a such that sum over i of angleBetween(a_i, a) is minimized.

This is an optimization problem which can be solved using a numerical optimizer. Several of the answers here claim to provide simpler closed forms, or at least better approximations.

Statistics

As you point out in your article, you need to assume errors follow a Gaussian distribution to justify using least squares as the maximum likelyhood estimator. So in this application, where is the error? Is the random error in the position of two things, and the angle is just the normal of the line between them? If so, that normal will not follow a Gaussian distribution, even if the error in point position does. Taking means of angles only really makes sense if the random error is observed in the angle itself.

Here you go! The reference is https://www.wxforum.net/index.php?topic=8660.0

def avgWind(directions):
    sinSum = 0
    cosSum = 0
    d2r = math.pi/180 #degree to radian
    r2d = 180/math.pi
       
    for i in range(len(directions)):
        sinSum += math.sin(directions[i]*d2r)
        cosSum += math.cos(directions[i]*d2r)
      
    return ((r2d*(math.atan2(sinSum, cosSum)) + 360) % 360)
a= np.random.randint(low=0, high=360, size=6)
print(a)
avgWind(a)
Related