Отримання підрахунку унікальних значень у стовпці в bash


95

У мене є файли з обмеженими вкладками з кількома стовпцями. Я хочу підрахувати частоту зустрічання різних значень у стовпці для всіх файлів у папці та відсортувати їх у порядку зменшення підрахунку (спочатку найбільший підрахунок). Як мені це зробити в середовищі командного рядка Linux?

Він може використовувати будь-яку загальну мову командного рядка, наприклад awk, perl, python тощо.

Відповіді:



68

Ось спосіб зробити це в оболонці:

FIELD=2
cut -f $FIELD * | sort| uniq -c |sort -nr

Це те, у чому Bash чудово підходить.


22
"Сорт" речі ... ар-ар-ар! :)
Джон Рікс,

3
Своєрідна унікальна штучка. : P (btw. Використання -d,для розмежування полів комою або будь-яким іншим роздільником).
cprn

4
Я використовував cut -f 1 -d ' '. Дуже дякую. :)
Альфонсо Нішікава

8

Сайт GNU пропонує цей гарний сценарій awk, який друкує і слова, і їх частоту.

Можливі зміни:

  • Ви можете прокласти конвеєр sort -nr(і повернути назад wordі freq[word]), щоб побачити результат у порядку зменшення.
  • Якщо ви хочете певний стовпець, ви можете опустити цикл for і просто написати freq[3]++- замініть 3 номером стовпця.

Ось:

 # wordfreq.awk --- print list of word frequencies

 {
     $0 = tolower($0)    # remove case distinctions
     # remove punctuation
     gsub(/[^[:alnum:]_[:blank:]]/, "", $0)
     for (i = 1; i <= NF; i++)
         freq[$i]++
 }

 END {
     for (word in freq)
         printf "%s\t%d\n", word, freq[word]
 }

2
Чудовий приклад сценарію. Це демонструє стільки можливостей awk.
Девід Манн,

Цей скрипт був корисним для мене, щоб визначити, на які рядки в робочій книжці Excel мені дійсно потрібно було звернути увагу :) (скопіював вміст Excel у текстовий файл, використовую awk та, voila !, я можу зробити файл шаблону для grep -n) .
Jubbles

6

Perl

Цей код обчислює входження всіх стовпців і друкує відсортований звіт для кожного з них:

# columnvalues.pl
while (<>) {
    @Fields = split /\s+/;
    for $i ( 0 .. $#Fields ) {
        $result[$i]{$Fields[$i]}++
    };
}
for $j ( 0 .. $#result ) {
    print "column $j:\n";
    @values = keys %{$result[$j]};
    @sorted = sort { $result[$j]{$b} <=> $result[$j]{$a}  ||  $a cmp $b } @values;
    for $k ( @sorted ) {
        print " $k $result[$j]{$k}\n"
    }
}

Збережіть текст як columnvalues.pl
Запустіть його як: perl columnvalues.pl files*

Пояснення

У верхньому рівні циклу while:
*
Переведіть петлю на кожен рядок комбінованих вхідних файлів * Розділіть рядок на масив @Fields
* Для кожного стовпця збільшуйте структуру даних масиву хешів результатів

У циклі верхнього рівня for:
* Проведіть цикл масиву результатів
* Виведіть номер стовпця
* Отримайте значення, що використовуються в цьому стовпці
* Відсортуйте значення за кількістю випадків
* Вторинне сортування на основі значення (наприклад, b проти g vs m проти z)
* Перебирайте хеш результату, використовуючи відсортований список
* Надрукуйте значення та кількість кожного входження

Результати засновані на зразкових вхідних файлах, наданих @Dennis

column 0:
 a 3
 z 3
 t 1
 v 1
 w 1
column 1:
 d 3
 r 2
 b 1
 g 1
 m 1
 z 1
column 2:
 c 4
 a 3
 e 2

.csv введення

Якщо ваші вхідні файли .csv, змініть /\s+/на/,/

Затуманення

У потворному змаганні Perl особливо добре обладнаний.
Цей однокласник робить те саме:

perl -lane 'for $i (0..$#F){$g[$i]{$F[$i]}++};END{for $j (0..$#g){print "$j:";for $k (sort{$g[$j]{$b}<=>$g[$j]{$a}||$a cmp $b} keys %{$g[$j]}){print " $k $g[$j]{$k}"}}}' files*

2

Рубін (1,9+)

#!/usr/bin/env ruby
Dir["*"].each do |file|
    h=Hash.new(0)
    open(file).each do |row|
        row.chomp.split("\t").each do |w|
            h[ w ] += 1
        end
    end
    h.sort{|a,b| b[1]<=>a[1] }.each{|x,y| print "#{x}:#{y}\n" }
end

5
Це дуже цікаво, як тому, що я його використовував, так і працював, а також тому, що я просто вражений тим, наскільки потворний рубін .. Я подумав, що перл поганий!
ryansstack

На захист Рубіна це можна було б поправити. Наприклад, використовуючи each_with_objectсеред іншого. Словом, це дещо грубо написано.
Рамбатіно
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.