-1

2 つの列を持つテキスト ファイルがいくつかあります。最初の列はアミノ酸の位置、2 番目の列はアミノ酸の名前です。すべてのファイルから各アミノ酸の総数を取得したいと考えています。一意の値のみが必要です。次の例では、合計 no:of LEU は 2 です (1 つは file1 から、もう 1 つは 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
4

9 に答える 9

2

ファイルが 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
于 2013-04-07T05:01:07.133 に答える
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]
于 2013-04-07T04:05:32.650 に答える
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]))
于 2013-04-07T04:05:52.977 に答える
0

Python、Perl、および Awk について言及しました。

3 つすべてで、アイデアは同じです。ハッシュを使用して値を格納します。

ハッシュは配列に似ていますが、各エントリは場所ではなくキーでインデックス付けされます。ハッシュでは、そのキーを持つエントリは 1 つしか存在できません。このため、値が以前に出現したかどうかを確認するためにハッシュが使用されます。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

まず、2 つのループが必要です。1 つはすべてのファイルをループするループで、もう 1 つは特定のファイルの各行をループするループです。

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;
       }
    }
}

さて、あなたがユニークと言ったとき、あなたは位置ではなくアミノ酸だけについて話していたと思います. はsplit2 つの値を分割しており、アミノ酸だけを見ています。位置も重要な場合は、それを%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私は、数値部分をゼロで埋められた 10 進数に、アミノ酸を大文字にフォーマットするために使用します。こちらです:

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以前は合計の書式を設定していたことに注意してください。

于 2013-04-07T04:42:07.113 に答える
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
于 2013-04-07T06:48:26.933 に答える
0

ただのperlワンライナー:

perl -anE'$h{$F[1]}++}{say"total no:of $_ - $h{$_}"for keys%h'
于 2013-04-07T07:28:27.893 に答える