in reply to Average start time handling midnight

There does not seem to be a general solution to this problem. You did not mention how many reading you must average. A 'solution' which works well for two readings may fail for three or more. The article https://en.wikipedia.org/wiki/Mean_of_circular_quantities suggests an algorithm that seems to always do what we want. Too bad it is so complex.
Bill
  • Comment on Re: Average start time handling midnight

Replies are listed 'Best First'.
Re^2: Average start time handling midnight
by pryrt (Abbot) on Jul 21, 2016 at 15:52 UTC

    Maybe I'm being too simplistic, but given the OP's restrictions, "usually start within a 6 hour window" and "handles times over midnight", I think it's doable. If the 6 hours ended just after midnight, you would need to handle times from 18:01 - 00:01; if it started just before midnight, you would need to handle 23:59 - 5:59. For simplicity's sake, I'd make my window 18:00 - 5:59. Thus,

    $n = 0; while ( ... ) { $hour += 24 if( $hour < 6 ); next if( $hour < 18 ); # ignore times outside the window $sum += 3600*$hour + 60*$min + $sec; $avg = $sum / ++$n; }

    For the $hour < 18 rule: if the time is before 6am, it's $hour would have already been adjusted to somewhere in range 24 to 29, so wouldn't trigger the <18 condition; if the time was after 6pm, it wouldn't trigger the condition; else, it will trigger the condition, and the time would be ignored.

    If OP wants a narrower or wider 'accept-range', just adjust the two comparisons appropriately.

    Other options would be to clamp times between 6am and noon to 05:59:59, and between noon and 6pm to 18:00:00, which will not ignore points, but manipulate them to fall within the "normal window".

    I understand there are issues in the general case, but with the restrictions given, I think things are well-defined enough, and this algorithm should give a mean closer to midnight than to noon, which seems to be what the OP wants.

Re^2: Average start time handling midnight
by oiskuu (Hermit) on Jul 21, 2016 at 20:54 UTC

    Not that complicated, really, although it does seem a bit silly to do trigonometry where simple arithmetic would suffice.

    #! /usr/bin/perl -wl my @times = qw( 17:00 19:00 11:00 13:00 23:00 01:00 10:30 13:00 19:40 01:20 16:00 02:00 ); # keep angles in range -pi .. pi sub _PI () { 2 * atan2(1, 0) } sub _TC () { 24 * 60 / (2 * _PI) } sub time2angle { map { my ($h, $m) = split /:/; _PI - (60 * $h + $m) / _TC } @_ } sub angle2time { map { my $m = int _TC * (_PI - $_); sprintf "%02d:%02d", $m / 60, $m % 60 } @_ } use List::Util qw( sum ); sub circ_avg { atan2 sum(map sin, @_), sum(map cos, @_) } for (; @times > 1; shift @times) { my @t = @times[0, 1]; print "@t => @{[angle2time circ_avg time2angle @t]}"; }

    Thank you for the wikipedia link.

      When averaging two times, yes, it's silly. But when averaging more than two, it comes out with a very different result.

      ... # your code thru the definition of sub circ_avg; print "@times"; print " => circle vs line"; print " => @{[angle2time circ_avg time2angle @times]} vs @{ +[angle2time( sum( time2angle @times ) / @times ) ]}"; for (; @times > 1; shift @times) { my @t = @times[0, 1]; print "@t => @{[angle2time circ_avg time2angle @t]} vs @{[angle2ti +me( sum( time2angle @t ) / @t ) ]}"; } __END__ __OUTPUT__ 17:00 19:00 11:00 13:00 23:00 01:00 10:30 13:00 19:40 01:20 16:00 02:0 +0 => circle vs line => 17:46 vs 12:12 17:00 19:00 => 18:00 vs 18:00 19:00 11:00 => 15:00 vs 15:00 11:00 13:00 => 12:00 vs 12:00 13:00 23:00 => 18:00 vs 18:00 23:00 01:00 => 00:00 vs 12:00 01:00 10:30 => 05:45 vs 05:45 10:30 13:00 => 11:45 vs 11:45 13:00 19:40 => 16:20 vs 16:20 19:40 01:20 => 22:30 vs 10:30 01:20 16:00 => 20:40 vs 08:40 16:00 02:00 => 21:00 vs 09:00

      The pairs of times come out to a simple average that mostly matches the circles (except on the ones with midnight between time1 and time2); but you get very different results between the two averages for the entire list. Previously, I had compared my own implementation of the angular average (yours is better) to the results of salva's solution of finding the center-with-minimum-variance and found that the results for salva's example list (or a list of random times) gave very similar means to the angular average, which would be very different from the arithmetic mean for the same set of data

Re^2: Average start time handling midnight
by QM (Parson) on Jul 22, 2016 at 10:50 UTC
    Perhaps equivalent:

    Convert the time to radians. Treat all times as unit vectors in polar coordinates, with the time_in_radians as the angle. Convert the polar (1, time_in_radians) to Cartesion (x,y). Sum all of the xs and ys separately, (optionally averaging them, again separately), and convert the result back to polar. The average time is the angle. The averaged magnitude might be interesting also.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of