awk相同行名数据求和或求均值(二维数组形式)

需要求和或求均值文件为tab分割,第一行为列名,第一列为有重复名的数据,其他列为数值,示例:


image.png

使用awk求和:

awk -v ty=sum 'BEGIN{FS=OFS="\t"}NR==1{print $0;ncol=NF}NR>1{if($1 in che){dup[$1]+=1;for(i=1;i<NF+1;i++){num[$1,i]=$i+num[$1,i]}}else{che[$1]=$0;for(i=1;i<NF+1;i++){num[$1,i]=$i}}}END{for(i in che){if(i in dup){if(ty=="sum"){printf i"\t";for(j=2;j<NF;j++){printf num[i,j]"\t"}print num[i,NF]}else if(ty=="mean"){dup[i]+=1;printf i"\t";for(j=2;j<NF;j++){printf num[i,j]/dup[i]"\t"}print num[i,NF]/dup[i]}}else{print che[i]}}}' 111

结果:


image.png

求均值也是相同的命令,只是ty改成mean,结果:


image.png

思路是在读取时用二维数组定位每一个值,再判断行名是否重复,重复的相加,记录相加次数;读取结束后判断,如果是无重复的则直接输出,节省时间和算力;如果是有重复的,再判断参数是sum还是mean,如果是mean就将sum值除以相加次数即可

awk -v ty=sum 'BEGIN{FS=OFS="\t"}NR==1{
  print $0;ncol=NF}NR>1{
  if($1 in che){
    dup[$1]+=1;
    for(i=1;i<NF+1;i++){
        num[$1,i]=$i+num[$1,i]
     }
  }else{
    che[$1]=$0;
    for(i=1;i<NF+1;i++){
      num[$1,i]=$i
    }
  }
 }END{
   for(i in che){
     if(i in dup){
        if(ty=="sum"){
           printf i"\t";
           for(j=2;j<NF;j++){
             printf num[i,j]"\t"}print num[i,NF]
        }else if(ty=="mean"){
           dup[i]+=1;
           printf i"\t";
           for(j=2;j<NF;j++){
             printf num[i,j]/dup[i]"\t"}print num[i,NF]/dup[i]
        }
      }else{
       print che[i]
      }
     }
}'

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容