Get highest absolute value for each row (awk)

Viewed 119

I have a file with multiple rows and columns tab delimeted such as:

ID    v1        v2      v3     v4      v5     v6
A10  -0.2134  -0.190  -0.114  0.400  10.678 -0.123  
A115 -0.5038  -0.559  -0.664  0.431   0.139 -0.860    
AAAS -0.9072  -0.990  -1.251  3.153  -0.756  0.674 

I would like to get the highest absolute number from each row and print if is negative or positive, and also print the header ID from the correspondent column, like:

A10   10.678 v5  
A115  -0.860 v6    
AAAS  3.153  v4 

I was able to calculate the min and max values from each row, but I am not sure how to get the highest absolute values and the ID:

 awk  'NR>1{a=0; b=0; for (i=1;i<=NF;i++) if ($i < a || i == 1)a = $i; else if($i > b|| i == 1)b = $i; print $1,a, b}' file

A10  -0.2134  10.678
A115 -0.860   0.431
AAAS -1.251   3.153
2 Answers
$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR == 1 {
    split($0,hdrs)
    next
}
{
    maxVal = 0
    for (i=2; i<=NF; i++) {
        val = ($i >= 0 ? $i : - $i) + 0
        if ( val >= maxVal ) {
            maxVal = val
            maxFld = i
        }
    }
    print $1, $maxFld, hdrs[maxFld]
}

.

$ awk -f tst.awk file
A10     10.678  v5
A115    -0.860  v6
AAAS    3.153   v4

If you can have multiple max values, e.g.:

$ cat file
ID      v1      v2      v3      v4      v5      v6
A10     -0.2134 10.678  -0.114  10.678  10.678  -0.123
A115    -0.5038 -0.559  0.860   0.431   0.139   -0.860
AAAS    -0.9072 -0.990  -1.251  3.153   -0.756  0.674

then the above script will print the header ID of the last max value. If you want to print the first instead then it's an obvious trivial tweak, and if instead you want to list all of the associated headers then:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR == 1 {
    split($0,hdrs)
    next
}
{
    delete val2hdrs
    maxVal = 0
    for (i=2; i<=NF; i++) {
        val = ($i >= 0 ? $i : - $i) + 0
        if ( val >= maxVal ) {
            maxVal = val
            maxFld = i
            val2hdrs[val] = (val in val2hdrs ? val2hdrs[val] "," : "") hdrs[i]
        }
    }
    print $1, $maxFld, val2hdrs[maxVal]
}

.

$ awk -f tst.awk file
A10     10.678  v2,v4,v5
A115    -0.860  v3,v6
AAAS    3.153   v4

almost the same

$ awk 'function abs(x) {return x>0?x:-x} 
       NR==1 {split($0,h); next} 
             {max=abs($2); mi=2; 
              for(i=3;i<=NF;i++) 
                if(max<(nm=abs($i))) 
                  {max=nm; mi=i}; 
              print $1,$mi,h[mi]}' file | column -t 

A10   10.678  v5
A115  -0.860  v6
AAAS  3.153   v4
Related