# Get average for all rows every 3 columns

I'm on Ubuntu 14.04. Given the tab-delimited file:

Samples Field Field2 Field3 Field4 Field5 Field6 Field7 Field8 Field9 Field10 Field11 Field12

Sample1 1 2 3 4 5 6 7 8 9 10 11 12

I want to get printed the average of columns (each 3) for all rows, outputting something like this:

Sample Field Field2 Field3 Field4

Sample 2 5 8 11

• Are the number of columns fixed? – Sobrique Feb 9 '17 at 13:52
• Hmm, yes. The average of '1,2,3' is 2. But the average of 4,5,6 is not 7.5! – Sobrique Feb 9 '17 at 13:59

I'd tackle it something like this:

``````#!/usr/bin/perl

use warnings;
use strict;

my \$field_count = 3;

#discard first row, as the fields don't match
my \$first_row = <>;
#iterate STDIN or files specified on command line, just like grep or sed do.
while ( <> ) {
#extract the name and values. Maybe you need a 'chomp' to remove linefeeds
#it works given your sample data, because the last field is a number.
my ( \$samplename, @fields ) = split;
my @new_fields;
while ( @fields ) {
#extract fields 3 at a time.
my @group = splice @fields, 0, \$field_count;
#sum them
my \$sum = 0;
\$sum += \$_ for @group;

my \$avg = \$sum / @group; #divide by number of elements in this group, so it'll work if there's 1 or 2 'trailing'.
#stash that in the new field list.
push @new_fields, \$avg;
}
#print the output line.
print join "\t", \$samplename, @new_fields,"\n"
}
``````
• clean, generic and robust +1 – JJoao Feb 9 '17 at 17:15

### A1 Perl: using a tradicional for all the lines

Assuming input format : sampleId, groups of 3 values

``````perl -nE '(\$out,@g)=split;                   #sampleId a1 b1 c1  a2 b2 c2 ...
while((\$a,\$b,\$c,@g)=@g){
\$out .= " ".(\$a+\$b+\$c)/3 }
say \$out '
``````

or

### A2 Perl: using just regular expressions, substitute and eval

``````perl -pe 's!\b(\d+)\s+(\d+)\s+(\d+)! (\$1+\$2+\$3)/3 !ge'
``````