in reply to rearrange data to min, avg, max

So you want to read in all the data for one timestamp, calculate the min, avg, max, and note the errorcode(s), and output the one-line summary, right? Something like (formerly untested but now updated and tested thanks to comments from Limbic~Region):
my $current_ts = ''; my $rowcount = 0; my ($min, $max, $sum, %ec); while (<>) { chomp; my ($ts, $v, $e) = split; if ($current_ts ne $ts) { if ($current_ts eq '') { $current_ts = $ts } else { &output_summary } $current_ts = $ts; ($min, $max, $sum) = ($v, $v, $v); %ec = ($e, 1); $rowcount = 1; } else { $min = $v if ($v < $min); $max = $v if ($v > $max); $sum += $v; ++$rowcount; ++$ec{$e}; } } &output_summary; sub output_summary { printf "%s\t%g\t%g\t%g\t%s\n", $current_ts, $min, $max, $sum/$rowcou +nt, join(',', keys %ec); }

The PerlMonk tr/// Advocate

Replies are listed 'Best First'.
Re: Re: rearrange data to min, avg, max
by Limbic~Region (Chancellor) on Apr 30, 2004 at 16:06 UTC
    Roy Johnson,
    I understand it is un-tested, so some nits:
    • When you call the output_summary sub, you need to use () as a suffix or & as a prefix unless it has been previously seen.
    • You forgot to chomp newlines
    • ++$rowcount not +$rowcount
    • ++$ec{$e} not ++%ec{$e}
    • $min and $max need to have initial values prior to doing numerical comparisons
    Finally, I don't think it is working correctly - shouldn't the max for :20 be 4.151?.
    Here is my stab at it:
    #!/usr/bin/perl use strict; use warnings; my %data; while ( <DATA> ) { chomp; my ($stamp, $reading) = split; next if ! $stamp || ! defined $reading; $data{$stamp}{COUNT}++; $data{$stamp}{MAX} = $reading if ! defined $data{$stamp}{MAX} || $ +reading > $data{$stamp}{MAX}; $data{$stamp}{MIN} = $reading if ! defined $data{$stamp}{MIN} || $ +reading < $data{$stamp}{MIN}; $data{$stamp}{SUM} += $reading; } print join "\t" , "TIMESTAMP", "MAX", "MIN", "AVG"; print "\n"; for my $stamp ( sort keys %data ) { print join "\t", $stamp, @{$data{$stamp}}{ qw(MAX MIN) }, $data{$s +tamp}{SUM} / $data{$stamp}{COUNT}; print "\n"; }

    L~R