# medians for degree measurements

Steve Howell showell30 at yahoo.com
Mon Jan 25 19:36:19 CET 2010

```On Jan 24, 5:26 pm, Robert Kern <robert.k... at gmail.com> wrote:
> On 2010-01-23 05:52 , Steven D'Aprano wrote:
> > On Fri, 22 Jan 2010 22:09:54 -0800, Steve Howell wrote:
>
> >> On Jan 22, 5:12 pm, MRAB<pyt... at mrabarnett.plus.com>  wrote:
> >>> Steve Howell wrote:
> >>>> I just saw the thread for medians, and it reminded me of a problem
> >>>> that I need to solve.  We are writing some Python software for
> >>>> sailing, and we need to detect when we've departed from the median
> >>>> heading on the leg.  Calculating arithmetic medians is
> >>>> straightforward, but compass bearings add a twist.
> > [...]
> >> I like this implementation, and it would probably work 99.9999% of the
> >> time for my particular use case.  The only (very contrived) edge case
> >> that I can think of is when you have 10 bearings to SSW, 10 bearings to
> >> SSE, and the two outliers are unfortunately in the NE and NW quadrants.
> >> It seems like the algorithm above would pick one of the outliers.
>
> > The trouble is that median of angular measurements is not a meaningful
> > concept. The median depends on the values being ordered, but angles can't
> > be sensibly ordered. Which is larger, 1 degree north or 359 degrees? Is
> > the midpoint between them 0 degree or 180 degree?
>
> Then don't define the median that way. Instead, define the median as the point
> that minimizes the sum of the absolute deviations of the data from that point
> (the L1 norm of the deviations, for those familiar with that terminology). For
> 1-D data on the real number line, that corresponds to sorting the data and
> taking the middle element (or the artithmetic mean of the middle two in the case
> of even-numbered data). My definition applies to other spaces, too, that don't
> have a total order attached to them including the space of angles.
>
> The "circular median" is a real, well-defined statistic that is used for exactly
> what the OP intends to use it for.
>

I admitted pretty early in the thread that I did not define the
statistic with much rigor, although most people got the gist of the
problem, and as Robert points out, you can more clearly the define the
problem, although I think under any definition, some inputs will have
multiple solutions, such as (0, 90, 180, 270) and (0, 120, 240).  If
you've ever done lake sailing, you probably have encountered days
where the wind seems to be coming from those exact angles.

This is the code that I'll be using (posted by "Nobody").  I'll report
back it if it has any issues.

def mean(bearings):
x = sum(sin(radians(a)) for a in bearings)
y = sum(cos(radians(a)) for a in bearings)
return degrees(atan2(x, y))

def median(bearings):
m = mean(bearings)
bearings = [(a - m + 180) % 360 - 180 for a in
bearings]
bearings.sort()
median = bearings[len(bearings) / 2]
median += m
median %= 360
return median

```