Средние строки с одинаковым первым столбцом

Для файла с двумя столбцами:

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

Мне нужен способ объединить все строки с одинаковым идентификатором в один, который имеет среднюю высоту. В этом случае (69 + 67 + 65 + 62 + 59) / 5 = 64 и (29 + 26 + 21 + 20) / 4 = 24, поэтому выход должен быть:

 Id Avg.ht 510 64 601 24 

Как я могу это сделать с помощью sed / awk / perl?

  • расширять данные на основе оценок
  • проблема возникает при установке скриптов moses
  • как установить Padre в linux (CentOS)?
  • Как сделать URL из этого текста с наименьшими ресурсами?
  • df -k + как совместить строку корневого тома
  • Сопоставьте начало линии с чем-то там?
  • Удалить только заданные строки из данной колонки?
  • В чем разница между вызовом скрипта perl через sh или perl
  • 4 Solutions collect form web for “Средние строки с одинаковым первым столбцом”

    Использование awk:

    Входной файл

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

    Awk в оболочке:

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

    Или с Perl в оболочке:

     $ 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 

    Выход:

     id avg 601 = 24 id avg 510 = 64.4 

    И последнее для шутки, Perl темно-обфускации однострочный =)

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

    Вывод:

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

    Обратите внимание, что ваш результат выборки неправильный. Вы не можете получить среднее значение из 52, когда каждое значение для этого идентификатора равно 59 или больше.

    Кроме того, у вас есть буква l в одной из ваших колонок, маскировка под номером 1

    Взгляните на то, что делается здесь: http://www.sugihartono.com/programming/group-by-count-and-sorting-using-perl-script/

    Существенной трудной частью является операция «группа за». Связанный скрипт делает это с использованием хэша.

    В этой ссылке они вычисляют сумму, но получение среднего значения не будет сильно отличаться.

    С gnu datamash :

     datamash -H -s -g 1 mean 2 <file 
      GroupBy (Id) означает ()
     510 64,4
     601 24 

    Это указывает и g roups на 1 -ое поле, вычисляя mean значение 2 поля, сохраняя H eaders. Предполагается, что поля разделяются одной вкладкой. Используйте -W, --whitespace если они разделены несколькими пробелами или -t, --field-separator= для определения другого разделителя полей (пробел, запятая и т. Д.). Поскольку datamash требует отсортированного ввода, вывод будет отсортирован по сгруппированному столбцу.

    Linux и Unix - лучшая ОС в мире.