On Jan 24, 5:26 pm, Robert Kern <robert.k...@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...@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 -- http://mail.python.org/mailman/listinfo/python-list