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

2023-05-22  本文已影响0人  吃吃吃_就知道吃

需要求和或求均值文件为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]
      }
     }
}'

上一篇 下一篇

猜你喜欢

热点阅读