Các hàng trung bình có cùng cột đầu tiên


7

Cho một tệp có hai cột:

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

Tôi cần một cách để kết hợp tất cả các hàng có cùng ID thành một hàng có chiều cao trung bình. Trong trường hợp này, (69 + 67 + 65 + 62 + 59) / 5 = 64 và (29 + 26 + 21 + 20) / 4 = 24, vì vậy đầu ra phải là:

Id  Avg.ht
 510 64
 601 24

Làm thế nào tôi có thể làm điều đó bằng cách sử dụng sed / awk / perl?


Các id giống nhau được nhóm lại với nhau như trong mẫu?
choroba

Câu trả lời:


6

Sử dụng awk:

Các tập tin đầu vào

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

Awk in a shell:

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

Hoặc với Perl trong một vỏ:

$ 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

Đầu ra là:

id avg 601 = 24
id avg 510 = 64.4

Và cuối cùng cho trò đùa, một lớp lót tối tăm của Perl =)

perl -lane'END{for(keys(%h)){print"$_:".$h{$_}/$c{$_}}}($.>1)&&do{$h{$F[0]}+=$F[1];$c{$F[0]}++}' FILE

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";
}

Đầu ra:

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

Lưu ý rằng đầu ra mẫu của bạn là sai. Không có cách nào bạn có thể nhận được trung bình 52 khi mọi giá trị cho id đó là 59 hoặc lớn hơn.

Ngoài ra, bạn có một chữ cái ltrong một trong các cột của mình, giả dạng là số 1...


2

Với gnu datamash:

datamash -H -s -g 1 mean 2 <file
GroupBy (Id) có nghĩa là ()
510 64,4
601 24

Đây snhững nỗ lực và groups bởi 1lĩnh vực st tính 2lĩnh vực thứ meangiá trị, giữ gìn Headers. Nó giả sử các trường được phân tách bằng tab đơn. Sử dụng -W, --whitespacenếu chúng được phân tách bằng nhiều khoảng trống hoặc -t, --field-separator=để xác định dấu phân cách trường khác (dấu cách, dấu phẩy, v.v.). Vì datamashyêu cầu đầu vào được sắp xếp, đầu ra sẽ được sắp xếp theo cột được nhóm.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.