A maneira mais rápida de somar a coluna Nth no arquivo de texto

7

Eu tenho um arquivo CSV (em que o separador de campo é de fato vírgula) com 8 colunas e alguns milhões de linhas. Aqui está um exemplo:

1000024447,38111220,201705,181359,0,12,1,3090
1064458324,38009543,201507,9,0,1,1,1298
1064458324,38009543,201508,9,0,2,1,90017

Qual é a maneira mais rápida de imprimir a soma de todos os números em uma determinada coluna, bem como o número de linhas lidas? Você pode explicar o que faz isso mais rápido?

    
por Elifarley 02.07.2018 / 15:14

3 respostas

12

Datamash do GNU

$ datamash -t, count 3 sum 3 < file
3,604720

Alguns testes

$ time gawk -F',' '{ sum += $3 } END{ print sum, NR }' longfile
604720000000 3000000

real    0m2.851s
user    0m2.784s
sys     0m0.068s

$ time mawk -F',' '{ sum += $3 } END{ print sum, NR }' longfile
6.0472e+11 3000000

real    0m0.967s
user    0m0.920s
sys     0m0.048s

$ time perl -F, -nle '$sum += $F[2] }{ print "$.,$sum"' longfile
3000000,604720000000

real    0m3.394s
user    0m3.364s
sys     0m0.036s

$ time { cut -d, -f3 <longfile |paste -s -d+ - |bc ; }
604720000000

real    0m1.679s
user    0m1.416s
sys     0m0.248s

$ time datamash -t, count 3 sum 3 < longfile
3000000,604720000000

real    0m0.815s
user    0m0.716s
sys     0m0.036s

Portanto, mawk e datamash parecem ser a escolha do grupo.

    
por 02.07.2018 / 16:29
6

Awk é uma ferramenta rápida e eficiente para o processamento de arquivos de texto.

awk -F',' '{ sum += $3 }
           END{ printf "Sum of 3rd field: %d. Total number of lines: %d\n", sum, NR }' file

Exemplo de saída:

Sum of 3rd field: 604720. Total number of lines: 3

Nota conceitual :
Devo observar que todas essas alternativas que não são awk são capazes de executar mais rapidamente apenas para essas colunas numéricas "ideais". Custa apenas para você ter um formato um pouco mais complexo (por exemplo, com algumas informações adicionais a serem retiradas antes do cálculo <1064458324:a,<38009543:b,<201507:c,<9:d,<0:e,<1:f,<1:g,1298 ) e todas essas vantagens de velocidade desaparecerão (para não mencionar que algumas delas não serão capazes para executar o processamento necessário).

    
por 02.07.2018 / 15:22
1

Você pode usar cut para extrair o campo paste para inserir + sinais entre os números e bc para somar os mesmos. Você pode usar wc para contar as linhas.

Não tenho certeza qual seria o desempenho de milhões de linhas. Mas a regra de ouro do desempenho é, não adivinhe, medida. Você precisa criar um perfil de qualquer solução para ver se ela fornece o desempenho de que você precisa e para determinar se alguma alteração aumenta ou diminui o desempenho e em quanto.

Aqui está uma solução que soma um determinado campo e imprime o número de linhas:

echo -n "Sum: "
cut -d, -f3 <file |paste -s -d+ |bc
echo -n "Lines: "
wc -l <file

Saída:

Sum: 604720
Lines: 3

O campo é especificado pelo parâmetro -f# para cut , aqui cut -f3 .

    
por 02.07.2018 / 16:07