Agrupe todas as linhas com base na primeira coluna e, em seguida, calcule o total das segunda e terceira colunas

1

Eu preciso agrupar as linhas com base na primeira coluna para calcular a soma dos valores de toda a segunda linha e a soma dos valores de toda a terceira linha.

A segunda coluna deve ser calculada da seguinte forma: 10:56 = 10 * 60 + 56 = 656 segundos.

Arquivo de entrada:

     testing 00:34 123487
     archive 00:45 3973
     testing 09:16 800500
     archive 10:10 100000

Saída:

     archive 655 103973
     testing 590 923987
    
por ekassis 26.01.2017 / 19:19

3 respostas

2

Golfed para baixo para um one-liner. Funciona bem no GNU awk 3.1.7. Outras implementações do awk podem precisar do $2*60 substituído por substr($2,0,2)*60 . (Esperar que os gostos de '09: 16 'sejam interpretados como um valor inteiro de 9 é esticar um pouco as regras.)

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

Dando saída:

archive 655 103973
testing 590 923987

Alternativamente, uma abordagem de perl:

perl -e 'while(<>){/(\S+) +(\d+):(\d+) (\d+)/;$a{$1}+=$2*60+$3;$b{$1}+=$4;}for(keys %a){print "$_ $a{$_} $b{$_}\n"}'
    
por 26.01.2017 / 21:17
2

Usando este script awk com gawk :

{
   split($2,time,":");
   seconds=time[1]*60;
   seconds+=time[2];
   types[$1]["time"]+=seconds;
   types[$1]["othersum"]+=$3
}

END {
   for (record in types)
      print record, types[record]["time"], types[record]["othersum"]
}

gawk -f script.awk /path/to/input parece fazer o truque.

Se você precisar dele como uma linha, você pode fazer isso:

gawk '{split($2,time,":");seconds=time[1]*60;seconds+=time[2];types[$1]["time"]+=seconds;types[$1]["othersum"]+=$3} END {for (record in types) print record, types[record]["time"], types[record]["othersum"] }' /path/to/input
    
por 26.01.2017 / 19:45
0

Apenas por variedade

perl -pe 's/(\d+):(\d+)/60*$1+$2/e' file | datamash -Ws groupby 1 sum 2,3
archive 655     103973
testing 590     923987
    
por 27.01.2017 / 01:03