2013-04-07 5 views
-1

У меня есть текстовые файлы с двумя столбцами. первая колонка - это положение аминокислот, а вторая колонка - это имя аминокислот. Я хотел бы получить общее количество каждой аминокислоты из всех файлов. Мне нужны только уникальные значения. В следующем примере общее число no: LEU равно 2 (одно из файла 1, а другое - из файла2). Ваши предложения будут оценены!Получение числа уникальных значений

file1

54 LEU 
54 LEU 
78 VAL 
112 ALA 
78 VAL 

файл 2

54 LEU 
113 ALA 
113 ALA 
12 ALA 
112 ALA 

требуемый выход

total no:of LEU - 2 
total no:of VAL - 1 
total no:of ALA - 4 

ответ

2

Если у вас есть только два файла, просто использовать awk:

awk '{ a[$2]++ } END { for (i in a) print "total no:of", i, a[i] }' <(awk '!a[$1,$2]++' file1) <(awk '!a[$1,$2]++' file2) 

Если у вас есть много, много файлов, попробуйте этот awk сценарий. Бегите как:

awk -f script.awk file{1..200} 

Содержание script.awk:

{ 
    a[FILENAME,$1,$2] 
} 

END { 
    for (i in a) { 
     split (i,x,SUBSEP) 
     b[x[3]]++ 
    } 
    for (j in b) { 
     print "total no:of", j, b[j] 
    } 
} 

В качестве альтернативы, вот один вкладыш:

awk '{ a[FILENAME,$1,$2] } END { for (i in a) { split (i,x,SUBSEP); b[x[3]]++ } for (j in b) print "total no:of", j, b[j] }' file{1..200} 

Результаты:

total no:of LEU 2 
total no:of ALA 4 
total no:of VAL 1 
0
name_dict = {} 
for filename in filenames: 
    fsock = open(filename, 'r') 
    lines = fsock.readlines() 
    fsock.close() 
    for line in lines: 
     a = line.split() 
     key = a[-1] 
     if name_dict[key]: 
      name_dict[key] += 1 
     else: 
      name_dict[key] = 1 

for i in name_dict.items(): 
    print "total no:of ", i[0], " - ", i[1] 
0
with open('file1.txt', 'r') as f1, open('file2.txt', 'r') as f2: 
    # open both files, then close afterwards 
    data = f1.readlines().split() + f2.readlines.split() 
    # read the data, then split it by spaces 
d = {elem:data.count(elem) for elem in set(data[0::2])} 
for i in d: 
    print('total no:of {} - {}'.format(i, d[i])) 
0

открыть файл, прочитать строку, получить имя protien, если оно существует в словаре, добавьте 1 к нему или добавьте его в словарь.

protien_dict = {} 
openfile = open(filename) 
while True: 
    line = openfile.readline() 
    if line = "": 
      break 
    values = line.split(" ") 
    if protien_dict.has_key(values[1]): 
     protien_dict[values[1]] = protien_dict[values[1]] + 1 
    else: 
     protien_dict[values[1]] = 1 
for elem in protien_dict: 
    print "total no. of " + elem + " = " + protien_dict[elem] 
+0

'в то время как true': вам нужно' break' заявление или вы получите бесконечный цикл. –

0

collections.Counter особенно полезно - как вы уже догадались - счетные вещи !:

from collections import Counter 
counts = Counter() 
for filename in filenames: 
    with open(filename) as f: 
     counts.update(set(tuple(line.split()) for line in f if line.strip())) 
0

Вы упомянули Python, Perl и Awk.

Во всех трех случаях идея будет такой же: использование хэша для хранения значений.

Хеши похожи на массивы, за исключением того, что каждая запись индексируется ключом , а не местом. В хэше может быть только одна запись с этим ключом. Из-за этого хеши используются для проверки того, появились ли значения раньше. Вот краткий пример Perl:

my %value_hash; 
for my $value (qw(one two three one three four)) { 
    if (exists $value_hash{$value}) { 
     print "I've seen the value $value before\n"; 
    } 
    else { 
     print "The value of $value is new\n"; 
     $value_hash{$value} = 1; 
    } 
} 

Это напечатает:

The value of one is new 
The value of two is new 
The value of three is new 
I've seen the value of one before 
I've seen the value of three before 
The value of four is new 

Во-первых, вам нужно два контура: один Переберите все файлы, а другой цикл по каждой строке конкретный файл.

for my $file_name (@file_list) { 
    open my $file_fh, "<", $file_name 
     or die qw(File $file_name doesn't exist); 
    while (my $line = <$file_fh>) { 
     chomp $line; 
     ... 
    } 
} 

Далее мы будем вводить хэш сумм каждой аминокислоты и отслеживания хэша для этих аминокислот:

use strict; 
use warnings; 
use autodie; 

my %total_amino_acids; 
my @file_list = qw(file1 file2); #Your list of files 

for my $file_name (@file_list) { 
    open my $file_fh, "<", $file_name; 
    my %seen_amino_acid_before; # "Initialize" hash which tracks seen 
    while (my $line = <$file_fh>) { 
     chomp $line; 
     my ($location, $amino_acid) = split $line; 
     if (not %seen_amino_acid_before{$amino_acid}) { 
      $total_amino_acids{$amino_acid} += 1; 
     } 
    } 
} 

Теперь, я предполагаю, что, когда вы сказали уникальный , вы говорили только об аминокислоте, а не о положении. split разделяет два значения, и я только смотрю на аминокислоту. Если положение также важно, вы должны включить это в ключ из хэш-кода %seen_amino_acid_before. Это сложно, потому что я мог представить себе следующее:

54 LEU 
54 LEU 
054.00 LEU 

Это разные строки, но все они имеют одинаковую информацию. Вы хотите убедиться, что вы стандартизируете ключ позиции/аминокислоты.

while (my $line = <$file_fh>) { 
     chomp $line; 
     my ($location, $amino_acid) = split $line; 
     my $amino_acid_key = sprinf "%04d-%s", $location, uc $amino_acid; 
     if (not %seen_amino_acid_before{$amino_acid_key}) { 
      $total_amino_acids{$amino_acid} += 1; 
     } 
    } 

В выше, я создаю $amino_acid_key.Я использую sprintf для форматирования моей числовой части с нулевым заполнением десятичной точки, а аминокислота - в верхнем регистре. Таким образом:

54 LEU 
54 leu 
054.00 Leu 

все будут ключевыми 0054-LEU. Таким образом, способ ввода ваших данных в ваш файл не влияет на ваши результаты. Это может быть совершенно ненужным шагом, но что-то, что вы всегда должны учитывать. Например, если ваши данные генерируются компьютером, это, вероятно, не является проблемой. Если ваши данные вводятся группой более подготовленных студентов-градиентов посреди ночи, вам, вероятно, нужно беспокоиться о формате.

Теперь все, что вам нужно, это цикл, чтобы читать ваши данные:

for my $amino_acid (sort keys %total_amino_acids) { 
    printf "total no:of %4s - %4d\n", $amino_acid, $total_amino_acids{$amino_acid}; 
} 

Обратите внимание, я использовал, чтобы помочь printf форматировать итоги, так что они будут выстроены.

0

Другой вариант:

use strict; 
use warnings; 

my ($argv, %hash, %seen) = ''; 

while (<>) { 
    $argv ne $ARGV and $argv = $ARGV and undef %seen; 
    !$seen{ $1 . $2 }++ and $hash{$2}++ if /(.+)\s+(.+)/; 
} 

print "total no:of $_ - $hash{$_}\n" for keys %hash; 

Вывод на ваших наборов данных:

total no:of ALA - 4 
total no:of VAL - 1 
total no:of LEU - 2 
0

Just Perl Oneliner:

perl -anE'$h{$F[1]}++}{say"total no:of $_ - $h{$_}"for keys%h' 
0
ls file* | parallel 'sort -u {} >> tmp' ; awk '{print $2}' tmp | sort | uniq -c 

это дает выход как:

4 ALA

2 НОУ

1 VAL

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