Столбец суммы и количество строк - PullRequest
0 голосов
/ 21 апреля 2019

Я пытаюсь суммировать определенные числа в столбце 2, это работает с моим кодом.Но я хочу также посчитать, сколько раз повторяется одно и то же значение в столбце 2 и печатать в последнем столбце.

file1

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 ]

5 голосов
/ 21 апреля 2019

Переименовано в переменную и добавлена ​​красивая печать:

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
4 голосов
/ 21 апреля 2019

Символы пробела относительно недороги в наши дни, вам действительно стоит подумать о том, чтобы получить их для своего кода, особенно если вы хотите, чтобы другие читали его, чтобы помочь вам отладить его!Вот код, который вы разместили:

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

Обратите внимание, что это будет работатьas-не имеет значения, сколько у вас полей в каждой строке, и если вам нужно использовать другое поле для ключа, на который вы рассчитываете и суммируете, то вы просто меняете значение keyFldNr в разделе BEGIN с 2 на любое другое значениебыть.

3 голосов
/ 21 апреля 2019

Вы почти прибили его, вы не увеличиваете 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
2 голосов
/ 22 апреля 2019

внешняя программа не нужна, быстрее ~ 21мс, пробовал на чистом 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
2 голосов
/ 21 апреля 2019

Не-awk подход, использующий очень полезную 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 и количество строк в группе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...