Policz elementy w liniach za pomocą awk

2

Mam plik tekstowy rozdzielany tabulatorami zawierający dane takie jak

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

itd. itp.

Chciałbym przekształcić tę strukturę w

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

tak, że a, b, c i d stają się kolumnami; 1, 2 i 3 stają się jednym rzędem; a liczby oznaczają liczbę. Na przykład. 1 ma jeden „a” i dwa „d”.

Jak można to osiągnąć za pomocą awk lub podobnych narzędzi?

ashwin
źródło
Witamy w Super Użytkowniku! Formatowanie z pewnością może być mylące, jeśli jesteś nowy. Sprawdzić ten przewodnik . Tym razem naprawiłem to dla ciebie. Powodzenia!
Pops

Odpowiedzi:

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

Niekoniecznie wydajny lub elegancki, ale powinien być łatwy do odczytania i wykonania zadania. Ponadto wiersze są kolumnami, które niekoniecznie będą drukowane w porządku posortowanym. Kluczem jest użycie count[row,col] symulować wielowymiarową tablicę, która nie jest bezpośrednio obsługiwana w awk. Wyszukiwarka Google dla „awk multidimensional arrays” wyświetli kilka artykułów, w tym ten .

garyjohn
źródło
0

Oto rozwiązanie 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
terdon
źródło