Durchschnittliche Zeilen mit derselben ersten Spalte

7

Gegeben eine Datei mit zwei Spalten:

Id  ht
510 69
510 67
510 65
510 62
510 59
601 29
601 26
601 21
601 20

Ich brauche eine Möglichkeit, alle Zeilen mit derselben ID zu einer Zeile mit einer durchschnittlichen Höhe zusammenzuführen. In diesem Fall ist (69 + 67 + 65 + 62 + 59) / 5 = 64 und (29 + 26 + 21 + 20) / 4 = 24, daher sollte die Ausgabe sein:

Id  Avg.ht
 510 64
 601 24

Wie kann ich das mit sed / awk / perl machen?

Jack
quelle
Sind die gleichen IDs wie im Beispiel zusammengefasst zusammengefasst?
Choroba

Antworten:

6

Mit awk:

Die Eingabedatei

$ cat FILE
Id  ht
510 69
510 67
510 65
510 62
510 59
601 29
601 26
601 21
601 20

Awk in einer Muschel:

$ awk '
    NR>1{
        arr[$1]   += $2
        count[$1] += 1
    }
    END{
        for (a in arr) {
            print "id avg " a " = " arr[a] / count[a]
        }
    }
' FILE

Oder mit Perl in einer Shell:

$ perl -lane '
    END {
        foreach my $key (keys(%hash)) {
            print "id avg $key = " . $hash{$key} / $count{$key};
        }
    }
    if ($. > 1) {
        $hash{$F[0]}  += $F[1];
        $count{$F[0]} += 1;
    }
' FILE

Ausgabe ist:

id avg 601 = 24
id avg 510 = 64.4

Und zum Schluss noch ein Witz, ein dunkel verschleierter Perl-Einzeiler =)

perl -lane'END{for(keys(%h)){print"$_:".$h{$_}/$c{$_}}}($.>1)&&do{$h{$F[0]}+=$F[1];$c{$F[0]}++}' FILE
Gilles Quenot
quelle
2
#!/usr/bin/perl
use strict;
use warnings;

my %sum_so_far;
my %count_so_far;
while ( <> ) {
    # Skip lines that don't start with a digit
    next if m/^[^\d]/;

    # Accumulate the sum and the count
    my @line = split();
    $sum_so_far{$line[0]}   += $line[1];
    $count_so_far{$line[0]} += 1;
}

# Dump the output
print "Id Avg.ht\n";
foreach my $id ( keys %count_so_far ) {
    my $avg = $sum_so_far{$id}/$count_so_far{$id};
    print " $id $avg\n";
}

Ausgabe:

ire@localhost$ perl make_average.pl input.txt 
Id Avg.ht
 510 64.4
 601 24

Beachten Sie, dass Ihre Beispielausgabe falsch ist. Es gibt keine Möglichkeit, einen Durchschnitt von 52 zu erhalten, wenn jeder Wert für diese ID 59 oder größer ist.

Außerdem haben Sie einen Buchstaben lin einer Ihrer Spalten, der sich als Zahl tarnt 1...

ire_and_curses
quelle
2

Mit gnu datamash:

datamash -H -s -g 1 mean 2 <file
GroupBy (Id) mean ()
510 64.4
601 24

Dieser sort und gruppen von 1st Feld Berechnung 2nd meanFeldwertes, die Erhaltung Headers. Es wird davon ausgegangen, dass die Felder durch eine einzelne Registerkarte getrennt sind. Verwenden -W, --whitespaceSie diese Option, wenn sie durch mehrere Leerzeichen getrennt sind oder -t, --field-separator=um ein anderes Feldtrennzeichen (Leerzeichen, Komma usw.) zu definieren. Da datamasheine sortierte Eingabe erforderlich ist, wird die Ausgabe nach der gruppierten Spalte sortiert.

don_crissti
quelle