Contagem de elementos em linhas com awk

2

Eu tenho um arquivo de texto delimitado por tabulações contendo dados como

Col 1 Col 2
1     a
1     b
1     c
1     d
1     d
2     a
2     b
3     a

e assim por diante.

Eu gostaria de transformar essa estrutura em

  a b c d
1 1 1 1 2
2 1 1 1 1
3 1 0 0 0

para que, a, b, c e d se tornem colunas; 1, 2 e 3 tornam-se uma única linha; e os números representam contagem. Por exemplo. 1 tem um "a" e dois "d" s.

Como isso pode ser feito usando ferramentas awk ou similares?

    
por ashwin 10.08.2012 / 00:13

2 respostas

0

awk 'NR>1 {
    count[$1,$2]++;
    rows[$1]++;
    cols[$2]++;
}
END {
    printf("%3s", "");
    for (col in cols) {
        printf("%4s", col);
    }
    printf("\n");
    for (row in rows) {
        printf("%3d", row);
        for (col in cols) {
            printf(" %3d", count[row,col]);
        }
        printf("\n");
    }
}' data

Não necessariamente eficiente ou elegante, mas deve ser fácil de ler e executar o trabalho. Além disso, as linhas são colunas não serão necessariamente impressas na ordem classificada. A chave é o uso de count[row,col] para simular uma matriz multidimensional, que não é diretamente suportada no awk. Uma pesquisa do Google por "arrays multidimensionais do awk" exibirá vários artigos, incluindo este .

    
por 10.08.2012 / 03:19
0

Aqui está uma solução de PERL:

  perl -e '
    my (%col1, %col2); 
    while(<>){
        chomp; 
        @a=split(/\s+/); ## split line on whitespace
        $col2{$a[1]}++; ## Collect unique values from the 2nd column
        $col1{$a[0]}{$a[1]}++;## Count values per column/line
    } 
    my @l=sort keys %col2; 
    $"="\t"; ## Array record separator, using tabs to deal with variable size input
    print "\t@l\n"; 
    foreach my $c1 (sort keys(%col1)) {## For each column1 value
        print "$c1\t"; 
        my $str;
        for (my $i=0; $i<=$#l; $i++) {
        ## Collect the values for each position or 0 if there is none
        $col1{$c1}{$l[$i]}="0" unless defined($col1{$c1}{$l[$i]});
        $str.="$col1{$c1}{$l[$i]}\t";
        }
    chop($str); ## remove extra \t 
    print "$str\n";
    }' data   >ll
    
por 10.08.2012 / 06:07

Tags