总和列和计数行

时间:2019-04-21 10:44:43

标签: awk

我正在尝试对第2列中的某些数字求和,它可以与我的代码一起使用。但是我还想计算在第2列中重复相同的值并打印在最后一列中的次数。

文件1

36  2605 1 2
36  2605 1 2
36  2603 1 2
36  2605 1 2
36  2605 1 2
36  2605 1 2
36  2606 1 2

所需的输出

2603  36 1  2 1
2605 180 5 10 5
2606  36 1  2 1

我尝试过

awk '{a[$2]+=$1}{b[$2]+=$3}{c[$2]+=$4;count[$2]+=$2}END{for(i in a)print i,a[i],b[i],c[i],count[i]}' file1

预先感谢

5 个答案:

答案 0 :(得分:5)

重命名了vars,并添加了漂亮的印刷品:

awk '
{
    sum1[$2]+=$1
    sum3[$2]+=$3
    sum4[$2]+=$4
    count[$2]++

    len2=((l=length($2))>len2?l:len2)        
    len1=((l=length(sum1[$2]))>len1?l:len1)
    len3=((l=length(sum3[$2]))>len3?l:len3)
    len4=((l=length(sum4[$2]))>len4?l:len4)
    len5=((l=length(sum5[$2]))>len5?l:len5)
}
END {
    for(i in count) {
        printf "%*d %*d %*d %*d %*d\n",
            len2,i,len1,sum1[i],len3,sum3[i],len4,sum4[i],len5,count[i]
    }
}' file

输出:

2603  36 1  2 1
2605 180 5 10 5
2606  36 1  2 1

答案 1 :(得分:4)

这些天来,太空字符相对便宜,您应该真正考虑为代码获取一些,特别是如果您希望其他人阅读它来帮助您调试它的话!这是您发布的代码:

awk '{a[$2]+=$1}{b[$2]+=$3}{c[$2]+=$4;count[$2]+=$2}END{for(i in a)print i,a[i],b[i],c[i],count[i]}' file1

这里是经过代码美化程序(我使用过gawk -o)之后的情况:

{
        a[$2] += $1
}

{
        b[$2] += $3
}

{
        c[$2] += $4
        count[$2] += $2
}

END {
        for (i in a) {
                print i, a[i], b[i], c[i], count[i]
        }
}

看看如何通过添加一些空格现在变得非常容易理解,因此如何显着填充count[$2]的错误是显而易见的?一些有意义的变量名称也总是非常有用,而且我听说字母数字字符现在很特殊!

FWIW这是我的处理方式:

$ cat tst.awk
BEGIN { keyFldNr = 2 }
{
    numOutFlds = 0
    for (i=1; i<=NF; i++) {
        if (i != keyFldNr) {
            sum[$keyFldNr,++numOutFlds] += $i
        }
    }
    cnt[$keyFldNr]++
}
END {
    for (key in cnt) {
        printf "%s%s", key, OFS
        for (i=1; i<=numOutFlds; i++) {
            printf "%s%s", sum[key,i], OFS
        }
        print cnt[key]
    }
}

$ awk -f tst.awk file
2603 36 1 2 1
2605 180 5 10 5
2606 36 1 2 1

$ awk -f tst.awk file | column -t
2603  36   1  2   1
2605  180  5  10  5
2606  36   1  2   1

请注意,无论您每行有多少个字段,它都将按原样运行,如果您需要对要使用的键使用不同的字段进行计数和求和,则只需更改以下字段中的keyFldNr值即可:从2开始,直到您想要的任何部分。

答案 2 :(得分:3)

您几乎钉牢了,您没有适当地增加count[$2]

$ awk '{a[$2]+=$1;b[$2]+=$3;c[$2]+=$4;count[$2]++}
  END{for(i in a) print i,a[i],b[i],c[i],count[i]}' file
2603 36 1 2 1
2605 180 5 10 5
2606 36 1 2 1

答案 3 :(得分:2)

使用非常有用的GNU datamash的非笨拙方法,该方法专为此类任务而设计:

$ datamash -Ws groupby 2 sum 1,3,4 count 2 < input.txt
2603    36  1   2   1
2605    180 5   10  5
2606    36  1   2   1

读取为:对于第2列中具有相同值的每组行,显示该值,第1、3和4列的总和以及该组中的行数。

答案 4 :(得分:2)

不需要外部程序,速度更快〜21ms,可以在纯gnu awk上尝试

awk '{if($0~/^[A-Za-z0-9]/)a[NR]=$2" "$1" "$3" "$4}END{asort(a);$0="";for(;i++<NR;){split(a[i],b);if($1==""||b[1]==$1){$2+=b[2];$3+=b[3];$4+=b[4];$5++} else {print;$2=b[2];$3=b[3];$4=b[4];$5=1} $1=b[1]} print}' file1