У меня есть файлы с разделителями табуляцией и несколькими столбцами. Я хочу подсчитать частоту появления различных значений в столбце для всех файлов в папке и отсортировать их в порядке убывания количества (сначала максимальное количество). Как мне сделать это в среде командной строки Linux?
Он может использовать любой распространенный язык командной строки, такой как awk, perl, python и т. Д.
bash
command-line
frequency
фактор
источник
источник
-d,
для разделения полей запятой или любым другим разделителем).cut -f 1 -d ' '
. Большое спасибо. :)Сайт GNU предлагает этот красивый скрипт awk, который печатает как слова, так и их частоту.
Возможные изменения:
sort -nr
(и перевернутьword
иfreq[word]
), чтобы увидеть результат в порядке убывания.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] }
источник
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 vs g vs m vs z)
* Перебирать хэш результата, используя отсортированный список
* Распечатать значение и номер каждого вхождения
Результаты основаны на примерах входных файлов, предоставленных @Dennis
.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*
источник
Рубин (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
источник
each_with_object
, среди прочего. Короче, это несколько грубо написано.