Contagem de ocorrências repetidas em um CSV?

2

Eu tenho um CSV com colunas semelhantes às seguintes:

Team    Other Data  More Data   Result  Time
Knicks      A          F         Loss    2p
Celtics     B          E         Win     2p
Lakers      C          D         Loss    3p
Lakers      D          C         Loss    4p
Knicks      E          B         Win     4p
Lakers      F          A         Win     5p

Como posso ler o CSV e gerar os ganhos e perdas de cada equipe?

Por exemplo, minha saída desejada seria a seguinte:

1 Loss Knicks
1 Win Knicks
1 Win Celtics
2 Loss Lakers
1 Win Lakers

Neste momento, tenho este código:

#!/bin/bash
while IFS=, read -r team result
do
  echo $team, $result
done < teams.csv

Que produz a seguinte saída:

Team, Result   
Knicks, Loss
Celtics, Win
Lakers, Loss
Lakers, Loss
Knicks, Win

Como posso contar e armazenar o número de ocorrências de cada resultado para cada equipe? Idealmente, gostaria que esses dados fossem classificados por equipe.

    
por vipertherapper 16.07.2018 / 01:59

4 respostas

4

Usando matrizes em awk

Se os campos do arquivo de entrada estiverem separados por um ou mais caracteres de espaço em branco, você não precisará declarar o separador de campo:

awk 'NR>1 && NF { league[$1][$4]++ } END { for ( team in league ) for ( results in league[team] ) print league[team][results],results,team }' teams.txt

O mesmo código, formatado para a tela:

awk 'NR>1 && NF { league[$1][$4]++ }
     END { for ( team in league )
           for ( results in league[team] )
           print league[team][results],results,team }' teams.txt

Aqui, league[$1][$4]++ conta os números ( $4 , o quarto campo) de ganhos e perdas para cada equipe ( $1 , o primeiro campo) na liga (o arquivo de entrada).

NR>1 significa que awk irá ignorar o cabeçalho (a primeira linha).

Da mesma forma, NF (abreviação de NF>0 ) significa que awk examinará apenas linhas contendo pelo menos um campo. Em outras palavras, NF ignora linhas em branco.

A seção NR>1 && NF examina o arquivo de entrada e cria a matriz. Quando isso for concluído, a seção END imprimirá a matriz.

Se os campos do arquivo de entrada forem separados por vírgula, adicione BEGIN { FS="," ; OFS=" " } para definir os separadores de campo de entrada ( FS ) e de saída ( OFS ):

awk 'BEGIN { FS="," ; OFS=" " } NR>1 && NF { league[$1][$4]++ } END { for ( team in league ) for ( results in league[team] ) print league[team][results],results,team }' teams.csv

O mesmo código, formatado para a tela:

awk 'BEGIN { FS="," ; OFS=" " }
         NR>1 && NF { league[$1][$4]++ }
         END { for ( team in league )
               for ( results in league[team] )
               print league[team][results],results,team }' teams.csv

Saída:

1 Win Knicks
1 Loss Knicks
1 Win Lakers
2 Loss Lakers
1 Win Celtics

Adicione | sort -t " " -k 3 -k 2,2 ao final desse código, para classificar por equipe e depois por resultados por equipe.

Saída ordenada:

1 Win Celtics
1 Loss Knicks
1 Win Knicks
2 Loss Lakers
1 Win Lakers
    
por 16.07.2018 / 05:07
2

Tudo o que você precisa fazer é classificar o arquivo e passá-lo para uniq -c para contar ocorrências únicas:

sort teams.csv | uniq -c

Isso deve produzir uma saída assim:

      1 Celtics,Win
      1 Knicks,Loss
      1 Knicks,Win
      2 Lakers,Loss
    
por 16.07.2018 / 02:52
2

Com o datamash do GNU (e o awk para reorganizar as colunas, se isso for importante para você):

$ datamash -W --header-in groupby 1,4 count 4 < teams.csv | awk '{print $3, $2, $1}'
1 Loss Knicks
1 Win Celtics
2 Loss Lakers
1 Win Knicks
1 Win Lakers

Observe que, como não pedimos que o datamash seja classificado, isso agrupa apenas os resultados que já são adjacentes.

Se os seus dados forem realmente vírgula separados, substitua -W por -t,

    
por 16.07.2018 / 03:11
1

Você pode usar apenas sort e enviá-lo para uniq -c , mas isso incluirá Team, Result .

Para evitar isso:

$ awk 'NR>1 {print $4,$1}' team.csv | sort -k2 | uniq -c

Para explicar cada seção:

  • awk 'NR>1 {print $4,$1}' - Imprime todas as linhas maiores que a primeira com o resultado seguido pela equipe conforme especificado nas colunas 4 e 1 para a equipe e o resultado.
  • sort -k2 - Classifica pela equipe quando se torna a segunda coluna depois que awk opera.
  • uniq -c - conta o número de ocorrências únicas

A saída classificada por equipe:

1 Win Celtics
1 Loss Knicks
1 Win Knicks
2 Loss Lakers
1 Win Lakers
    
por 16.07.2018 / 03:18