获取唯一值的数量

时间:2013-04-07 03:57:37

标签: python perl awk

我有一些包含两列的文本文件。第一列是氨基酸的位置,第二列是氨基酸的名称。我想得到所有文件中每种氨基酸的总数。我只需要独特的价值观。在以下示例中,LEU的总数为:2(一个来自file1,另一个来自file2)。您的建议将不胜感激!

文件1

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

9 个答案:

答案 0 :(得分: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

答案 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]

答案 2 :(得分: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]))

答案 3 :(得分:0)

打开文件,读取一行,获取蛋白质的名称,如果它存在于词典中,添加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]

答案 4 :(得分: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()))

答案 5 :(得分: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;
       }
    }
}

现在,我假设当你说 unique 时,你只谈的是氨基酸,而不是位置。 split正在分割这两个值,我只是看着氨基酸。如果position也很重要,则必须将其包含在%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来帮助格式化总计,因此它们会排成一行。

答案 6 :(得分: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

答案 7 :(得分:0)

只需佩戴一个班轮:

perl -anE'$h{$F[1]}++}{say"total no:of $_ - $h{$_}"for keys%h'

答案 8 :(得分:0)

ls file* | parallel 'sort -u {}  >> tmp' ; awk '{print $2}' tmp | sort | uniq -c

这将输出为:

4 ALA

2 LEU

1 VAL