2012-03-13 2 views
1

У меня есть файлы с несколькими столбцами, и я хочу читать значения из определенного столбца. Я могу прочитать столбец, используя awk{print $column_number}.Извлечение данных из колонок unix

Каждый файл имеет разную длину столбцов, то есть некоторые могут составлять 1000 записей, а другим может быть всего 2 и так далее. Сами записи варьируются от 1 цифры до 5 цифр. Это одинаково для всех файлов.

Я хочу рассчитать диапазон наиболее повторяющихся значений. Например, если столбец гласит:

5 
93 
201 
2002 
20003 
20005 
20087 
31450 
31451 
31452 
31458 
52400 
52428 

, то я хочу, чтобы хранить 31,400 как наиболее неоднократного значение, то 20,000 и 52,000 в качестве второго и третьего наиболее наиболее часто повторяющихся значений и так далее. Вы можете сказать, что я округляю ценности, чтобы увидеть самые повторяющиеся числа, если это имеет смысл. Эти значения (наиболее часто повторяющихся, то второй наиболее неоднократное) можно считать кратные 100. Таким образом, в основном код должен выглядеть примерно так:

for f in ls path-to-the-files/*

do

while read i 

    do 
    <do the operation to sort and store the values> 
done   

done

Буду признателен за помощь в этом!

+0

ли все диапазоны последовательные куски 10000? – sethcall

+0

Нет, они могут быть 11000, 67500, почти все, если этот диапазон повторяется часто. К сожалению, следовало бы упомянуть об этом. Я редактировал 52 000 вопросов. – dawnoflife

+4

Я думаю, вам нужно лучше определить, что такое диапазон. 20000 и 52000 не являются диапазонами, они являются значениями. –

ответ

2

Это может работать для вас:

sed 's/.\?.$//;s/^$/0/;s/.$/,&00/;s/^,/0,/' file | sort | uniq -c | sort -nr 
4 31,400 
3 20,000 
2 52,400 
2 0,000 
1 2,000 
1 0,200 

Если вы не заинтересованы в использовании формата ,:

sed 's/.\?.$//;s/$/00/;s/^00$/0/' file | sort | uniq -c | sort -nr 
    4 31400 
    3 20000 
    2 52400 
    2 0 
    1 2000 
    1 200 
+0

Это не похоже на мои данные. Я просто получаю '1'' за все значения, т. Е. Он просто показывает, что каждое значение присутствует один раз. Он не учитывает количество значений в наблюдаемых диапазонах. – dawnoflife

+0

Я тестировал данные, предоставленные вами и работая в среде linux. Возможно, у вас есть пробелы с обеих сторон столбца данных. В этом случае поставьте 's/^ \ s * //; s/\ s * $ //;' в начале первого оператора sed. Без знания ваших данных и вашей среды трудно посоветовать. – potong

+0

Я использовал этот код только для столбца, и он работает. Я просто выплюнул колонку отдельно и запустил ее, чтобы получить результаты. К сожалению, некоторые из моих файлов являются двоичными, любая идея, как я извлекаю столбцы из них? – dawnoflife

1

Вы, кажется, хотите посчитать количество значений в каждом диапазоне 100, 0..99, 100..199, 200..299 и т. Д., А затем найти самый большой такой диапазон.

Возможно, вы можете сделать это в awk (и определенно в Python), но я собираюсь использовать Perl.

Я собираюсь скопировать номер столбца в программу; который может быть изменен (например, вариант в командной строке), если это необходимо. Я выбрал столбец 3, считая от 0.

#!/usr/bin/env perl 
use strict; 
use warnings; 
use constant colno => 3; 

my %ranges; 

while (<>) 
{ 
    my(@fields) = split /\s+/; 
    my($key) = int($fields[colno]/100); 
    $range{$key}++; 
} 

# The hash now contains the number of entries for each range that's present in the 
# data. Now we need to hack the data so that we can easily find the range(s) with 
# the largest counts. 
# Apply the Schwartzian Transform: http://en.wikipedia.org/wiki/Schwartzian_transform 

my @results = map { [$_->[0], $_->[1]] } 
       sort { $a->[1] <=> $b->[1] } 
       map { [$_, $ranges{$_}] } 
        keys %ranges; 

# And print the results 
foreach my $ref (reverse @results) 
{ 
    printf "%5d = %d\n", $ref->[0] * 100, $ref->[1]; 
} 

Для данных образцов (ватные с тремя предыдущими колоннами), выход:

31400 = 4 
20000 = 3 
    0 = 2 
52400 = 2 
2000 = 1 
    200 = 1 

Schwartzian Transform глубокая черная магия. Здесь может не понадобиться, но это работает. (И да, это первый раз, когда я использовал его.)


код Perl было весело (и, вероятно, довольно быстро), но если вы не имеете Perl на машине, то вам нужно альтернатива.

awk '{value = int($3/100); print value*100;}' files | 
sort | 
uniq -c | 
sort -nr 

awk код поднимает колонку 3 (считая от 1, а не 0!), Делит значение на 100 и преобразует его в целое число, а затем выводит значение, умноженное на 100; это дает группировку, которую вы хотите. Оставшийся sort | uniq -c | sort -nr конвейер является стандартной идиомой для подсчета вхождений и сортировки, так что наиболее часто появляется первая. На самом деле, часто бывает лучше оставить r из окончательной сортировки, так что последние несколько строк вывода являются наиболее интересными.

+0

Что такое 'my% range' в вашем коде. Мне нужно сначала установить пакет perl для cygwin, чтобы попробовать это. – dawnoflife

+0

'my% range;' объявляет хэш, который впоследствии ссылается (неповторимым способом Perl) как '$ range {$ key}' и т. Д. Да, для проверки этого потребуется Perl от Cygwin (или ActiveState). Я понятия не имею, можете ли вы сделать Шварцское преобразование или его эквивалент в 'awk'; мое чувство кишки «нет, это слишком много для« awk », но я могу продать его коротким. Это был интересный вопрос. Если вы посмотрите на канонический пример на странице Википедии, вы увидите, что первая карта, перечисленная выше, немного сложнее, чем приведенный там образец. Но только немного. Однако это похоже на линейный шум. –

+0

Я никогда раньше не работал с perl, поэтому я немного скептически отношусь к этому, но попробую это завтра в am. Вероятно, я столкнулся с некоторыми ошибками, реализующими код perl в cygwin. будет держать вас в курсе! Спасибо! – dawnoflife

Смежные вопросы