2016-08-12 4 views
0

最初の列に繰り返し値を持つタブ区切りファイルがあります。最初の列の単一の反復値は、2番目の列の複数の値に対応します。それはこのようなものになります。最初の列の順序の種類ごとに列IDに基づくファイルの解析:perl

AAAAAAAAAA1  m081216|101|123 
    AAAAAAAAAA1  m081216|100|1987 
    AAAAAAAAAA1  m081216|927|463729 
    BBBBBBBBBB2  m081216|254|260489 
    BBBBBBBBBB2  m081216|475|1234 
    BBBBBBBBBB2  m081216|987|240 
    CCCCCCCCCC3  m081216|433|1000 
    CCCCCCCCCC3  m081216|902|366 
    CCCCCCCCCC3  m081216|724|193 

を、私はそれに対応してちょうど配列を持つファイルに印刷しようとしています。ファイルの名前には、最初の列の繰り返しのシーケンスと、2番目の列のそれに対応するシーケンスの数を含める必要があります。上記の例では、私はそれぞれ3つのシーケンスの3つのファイルを持っています。最初のファイルは、「AAAAAAAAAA1.3.txt」のようなものを命名し、開いたときに次のようになり、次のようになります。

m081216|101|123 
    m081216|100|1987 
    m081216|927|463729 

私は他の同様の質問を見てきましたが、彼らは、ハッシュを使用して回答されています。列間の関係の数を維持する必要があるため、ハッシュを使用できないとは思いません。たぶんハッシュのハッシュを使う方法がありますか?私はわかりません。 ここまでは私のコードです。

use warnings; 
    use strict; 
    use List::MoreUtils 'true'; 

    open(IN, "<", "/path/to/in_file") or die $!; 

    my @array; 
    my $queryID; 

    while(<IN>){ 
      chomp; 
      my $OutputLine = $_; 
      processOutputLine($OutputLine); 
    } 


    sub processOutputLine { 
      my ($OutputLine) = @_; 
      my @Columns = split("\t", $OutputLine); 
      my ($queryID, $target) = @Columns; 
      push(@array, $target, "\n") unless grep{$queryID eq $_} @array; 
      my $delineator = "\n"; 
      my $count = true { /$delineator/g } @array; 
      open(OUT, ">", "/path/to/out_$..$queryID.$count.txt") or die $!; 
      foreach(@array){ 
        print OUT @array; 
      } 
    } 
+0

あなたはおそらくもループからのファイルの書き込みを削除したいと思う、またはあなたがよデータのすべての行でそれを上書きしてください。 –

答えて

3

私はまだハッシュをお勧めします。ただし、同じIDに関連するすべてのシーケンスは、そのIDキーの値である無名配列に格納します。これは実際には2行のコードです。あなたの入力して

use warnings; 
use strict; 
use feature qw(say); 

my $filename = 'rep_seqs.txt'; # input file name 
open my $in_fh, '<', $filename or die "Can't open $filename: $!"; 

my %seqs; 
foreach my $line (<$in_fh>) { 
    chomp $line; 
    my ($id, $seq) = split /\t/, $line; 
    push @{$seqs{$id}}, $seq; 
} 
close $in_fh; 

my $out_fh; 
for (sort keys %seqs) { 
    my $outfile = $_ . '_' . scalar @{$seqs{$_}} . '.txt'; 
    open $out_fh, '>', $outfile or do { 
     warn "Can't open $outfile: $!"; 
     next; 
    }; 
    say $out_fh $_ for @{$seqs{$_}}; 
} 
close $out_fh; 

私はそれらに対応する3行それぞれにAA..._count.txtという名前の希望のファイルを、取得します。 |で区切られた項目を分割する必要がある場合は、例えば書き出す際にそれを行うことができます。我々pushたら、あればすでに

  • タブの問題(スペースに変換?)がある場合

    ' 'が使用していない

    コメント

    • キー$seqs{$id}の匿名配列が作成されます。コメントを参照してください。

    • ファイルハンドルが閉じられ、すべてのopenに再オープンするので、不要毎回クローズする


    splitのデフォルトのパターンは、特定の動作をトリガーする、' 'ではありません - それは一致します"任意の連続する空白"、および先頭の空白を省略します。 (パターン/ /は単一のスペースに一致し、この特殊な動作は' 'となりません)。splitページのより詳細な説明を参照してください。したがって、splitの場合、これはちょっと慣れ親しんでいるため、不特定多数のスペースで分割するときは' 'を使用することをお勧めします。これはおそらく最も一般的な用途であり、デフォルトです。このコメントと更新を促すメッセージ(/\s+/のオリジナルポストがあります)のBorodinに感謝します。' '$_と一緒にデフォルトであるため、この場合には、我々はそれを短縮することができ

    注少し

    for (<$in_fh>) { 
        chomp; 
        my ($id, $seq) = split; 
        push @{$seqs{$id}}, $seq; 
    } 
    
  • +0

    あなたの助けと洞察力のあるコメントをありがとう。私はあなたの応答で、 "close $ fh_in;"と気付きました。本当に "close $ in_fh;"でなければなりません。また、私の質問の後半については、その特定のファイルに含まれるシーケンスの数を各ファイルの名前を追加する方法についての任意のトリックがありますか?あなたのすばらしい助けをもう一度ありがとう! – Rob

    +0

    @Robこれらのコメントありがとうございます!私は '$ specs_fh'としてファイルハンドルにラベルを付けるのが好きです。そして、名前にカウントを追加するというあなたの要求を忘れてしまったので、今追加します。帰属ありがとうございます。 – zdim

    +0

    @Robファイル名にカウントを追加しました。 'scalar'はリストの長さ(要素の数)を返し、配列参照は' @ {array_ref} 'の逆参照によってリストとして使うことができるので、とてもシンプルです。私が実際に ''を望むならば、ファイル名のカウントを '_'で区切ります。' '_ ''を' '。 ''に変更してください。 – zdim

    関連する問題