如果其他列中的值匹配,则为平均列,并打印为附加列

时间:2017-08-03 16:42:49

标签: linux awk

我有一个这样的文件:

Score      1      24      HG      1  
Score      2      26      HG      2  
Score      5      56      RP      0.5  
Score      7      82      RP      1  
Score      12     97      GM      5  
Score      32     104     LS      3  

如果第4列相同,我想平均第5列,并将平均数打印为第6列,使其看起来像这样:

Score      1      24      HG      1      1.5
Score      2      26      HG      2      1.5  
Score      5      56      RP      0.5    0.75  
Score      7      82      RP      1      0.75  
Score      12     97      GM      5      5  
Score      32     104     LS      3      3  

我尝试了一些我在这里找到的解决方案。 e.g。

awk '{ total[$4] += $5; ++n[$4] } END { for(i in total) print i, total[i] / n[i] }'

但他们都以此结束:

HG      1.5
RP      0.75  
GM      5  
LS      3

由于我丢失了大量信息,这是不可取的。

2 个答案:

答案 0 :(得分:2)

你可以遍历你的表两次:计算第一次迭代时的平均值(就像你已经做的那样),然后在第二次迭代时将它们打印出来:

awk 'NR==FNR { total[$4] += $5; ++n[$4] } NR>FNR { print $0, total[$4] / n[$4] }' file file

最后注意file两次。在经历"第一次"文件NR==FNR,我们将适当的值相加,将它们保存在内存中(变量totaln)。在"第二"文件遍历,NR>FNR,我们打印出所有原始数据+平均值:

Score      1      24      HG      1     1.5
Score      2      26      HG      2     1.5
Score      5      56      RP      0.5   0.75
Score      7      82      RP      1     0.75
Score      12     97      GM      5     5
Score      32     104     LS      3     3

答案 1 :(得分:1)

您可以使用1次传递文件,但是您必须在内存中存储整个文件,因此磁盘i / o与内存权衡:

awk '
    BEGIN {FS = OFS = "\t"} 
    {total[$4] += $5; n[$4]++; line[NR] = $0; key[NR] = $4} 
    END {for (i=1; i<=NR; i++) print line[i], total[key[i]] / n[key[i]]}
' file