2013-04-07 105 views
-1

我有一些带有两列的文本文件。第一列是氨基酸的位置,第二列是氨基酸的名称。我想从所有文件中获得每个氨基酸的总数。我只需要独特的价值。在下面的例子中,LEU的total no:是2(一个来自file1,另一个来自file2)。您的建议将不胜感激!获取唯一值的数量

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脚本。的script.awk

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

内容:像运行

{ 
    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'陈述或者你会得到一个无限循环。 – 2013-04-07 04:12:02

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。这样,数据输入到文件中的方式不会影响结果。这可能是一个完全不必要的步骤,但应该始终考虑。例如,如果您的数据是由计算机生成的,那么这可能不是问题。如果您的数据是在半夜中由一群过度劳动的研究生输入的,那么您可能需要担心格式。

现在,所有你需要的是一个循环读取数据:我以前printf帮助格式化总计

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

通知,所以他们会排起长队。

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

只是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 LEU

1 VAL