2

私はPerlの初心者であり、プログラミング全般(1か月未満の経験)です。

より大きな問題を解決するためには、解決する必要のある問題に困惑しています。

基本的に、次のような2つの配列があります。

@array1 = ('NM_1234' , '1452' , 'NM_345' , '5008' , 'NR_6145' , '256');
@array2 = ('NM_5673' , '2' , 'NM_345' , '5' , 'NR_6145' , '10');

@array1ID番号とそれに続く長さが含まれます。id番号はヌクレオチド配列で、長さは配列の長さです。

@array2ID番号の後にそれぞれのG-Quadruplex構造の数が含まれるため、一部のシーケンスにはそのような構造が2つしか含まれず、他のシーケンスには10以上が含まれます。

基本的な問題は、一致するすべてのID番号@array2の「長さ番号」@array1(たとえば、5008、256)に追加する必要があることです。

たとえば、両方の配列でNM_345が一致する場合、 5008を追加して、最終結果がNM_345,5,5008のようになるようにする必要があります。

同様に、NR_6145および他のそのような一致(に20,000を超えるID番号があります@array2

これまでのところ、両方の配列で同じID番号を検索できるコードを記述できました。コードは次のとおりです。

#Enter file name
print "Enter file name: ";
$in =<>;
chomp $in;

open(FASTA,"$in") or die;

@data = <FASTA>; #Read in data        
$data = join ('',@data); #Convert to string
@data2 = split('\n',$data); #Explode along newlines

#Enter 2nd file name
print "\n\nEnter 2nd file name: ";
$in2=<>;
chomp $in2;

open(FASTA,"$in2") or die;
@entry =<FASTA>; #Read in data

$entry = join('',@entry); #Convert to string
@entry2 = split('\n',$entry); #Explode along newlines

my %seen;
for  $item (@data2) {
    if($item =~ /([0-9]+)/){
        push @{$seen{$key}}, $item;#WHAT IS THIS DOING? HOW?
    }
}

for my $item (@entry2) {
    if ($item =~ /([0-9]+)/){
        if (exists $seen{$key}) {
            print $item,"\n";
        };        
    }
}
exit;

ここで、このソリューションの2つの配列から同じ要素を見つけるコードを導出したので、完全なクレジットはChas.Owensにあります:https ://stackoverflow.com/a/1064929/1468737 。そしてもちろん、私はまだこの部分を完全には理解していません:

push @{$seen{$key}}, $item;#WHAT IS THIS DOING? HOW?

ハッシュ値の配列か何かのように見えますか?

では、@array1から@array2にlength要素を追加するにはどうすればよいですか?スプライスコマンドを使用する必要があると思いますが、どうすればよいですか?

私の希望する出力は次のようになります。

NM_345,5,5008 <br>
NM_6145,10,256<br>
etc

また、この出力をファイルに保存する必要があります。このファイルは、後で分析されて、長さとG-quadruplex数の間に相関関係があるかどうかが確認されます。

どんな助けや入力も深く感謝します。

私の問題を解決するために時間を割いていただきありがとうございます!


編集:この編集は、データファイルがどのように見えるかを示すためのものです。それらは基本的に私が書いた他のプログラムからのプットプットファイルです。

私の最初のファイル、Transcriptlength.faという名前で、40,000を超えるID番号が入って@array1いるのは次のようになります。

NR_037701
3353

NM_198399
2414

NR_026816
601

NR_027917
658

NR_002777
1278

Quadcount.AllGtranscripts.faという名前の2番目のファイルには、20,000を超えるid番号が入力されて@array2おり、次のようになります。

NM_000014   
1

NM_000016   
3

NM_000017   
19

NM_000018   
2

NM_000019   
3

NM_000020   
30

NM_000021   
1

NM_000022   
2

NM_000023   
5

NM_000024   
1

NM_000025   
15

NM_000029   
5
4

4 に答える 4

1

データファイルの読み取りと必要な出力の生成に問題があるようです。ファイルデータの例を示さない限り、問題のその部分を支援することはできませんが、ここに出力を正しく生成するための解決策があります。

データをハッシュに保存すると、特定のシーケンスIDの長さと構造数に直接アクセスできるため、最適です。幸い、説明したように配列された配列は、簡単な割り当てで簡単にハッシュに変換できるため、この短いプログラムは、表示されている配列から必要な処理を実行します。

ループ内のリストは、 10進数以外の文字を含む要素のみを選択することによりgrep /\D/, @array2、すべてのシーケンスIDを選択するだけです。@array2シーケンスが表示される順序が重要な場合に備えて、このようにしました。最終的なプログラムでは、データを配列に読み込むのではなく、ファイルから直接処理する必要があるため、これは問題になりません。

use strict;
use warnings;

my @array1 = ( NM_1234 1452   NM_345 5008   NR_6145 256 );
my @array2 = ( NM_5673    2   NM_345    5   NR_6145  10 );

my %lengths = @array1;
my %counts = @array2;

for my $id (grep /\D/, @array2) {
  my $length = $lengths{$id};
  printf "%s,%s,%s\n", $id, $length, $counts{$id} if $length;
}

出力

NM_345,5008,5
NR_6145,256,10

アップデート

ファイルデータは、データファイル内のレコードが空白行で区切られている段落モードを設定するのに理想的です。これを実現するには、入力レコードの区切り変数$/を空の文字列に設定します""

この改訂されたプログラムは、最初のファイルからレコードを読み取り、それらを空白で分割し(空白にはスペース、タブ、改行などが含まれます)、%lengths各シーケンスIDをその長さに関連付けるハッシュを作成します。

2番目のファイルについても同じことが行われ、今回はシーケンスIDがハッシュに表示されるかどうかがチェックされます。その場合、完全なレコードが出力されます。

use strict;
use warnings;

my $fh;
my %lengths;

$/ = "";

open $fh, '<', 'Transcriptlength.fa'
    or die qq(Unable to open "Transcriptlength.fa": $!);

while (<$fh>) {

  my ($id, $length) = split;
  next unless $id;

  $lengths{$id} = $length;
}

open $fh, '<', 'Quadcount.AllGtranscripts.fa'
    or die qq(Unable to open "Quadcount.AllGtranscripts.fa": $!);

while (<$fh>) {

  my ($id, $count) = split;
  next unless $id;

  my $length = $lengths{$id};
  next unless $length;

  print join(',', $id, $count, $length), "\n";
}

残念ながら、選択したサンプルデータには一致するシーケンスIDが含まれていないため、そのデータに対して実行した場合、このプログラムからの出力はありません。実際のファイルの生産性が向上します。

于 2012-06-20T23:57:06.377 に答える
1

1つの質問に対して質問が多すぎます...しかし、とにかくここに行きます:

push @{$seen{$key}}, $item;

%seenはハッシュ(または連想配列)であるため、そのキーに関連付けられた値$seen{$key}から回復します。次に、この値は配列参照として扱われ、演算子を使用して配列に変換されます。最後に、この配列の最後に追加されます。%seen$key@{}$item

長さの意味がわかりません...前の配列の長さですか?

そして、これをファイルに保存するにprint()は、スクリプトを作成し、スクリプトの実行時にファイルにリダイレクトする必要があります。次に例を示します。

./my_perl_script.pl > my_output_file

open()同じことがファイル入力にも当てはまります。実際にそうする必要はありませんclose()。これは、コーディングがより柔軟で高速です。

./my_perl_script.pl < my_input_file

これにより、これをより簡単な方法でパイプ処理し、他のスクリプト/プロセスとの間でデータを渡すことができます。もちろん、両方のリダイレクトを同時に使用できます。

./my_perl_script.pl < my_input_file > my_output_file

また、ファイルに保存する必要もありません(とにかく処理されたデータのコピーを用意することは常に賢明です)。また、結果を他のプロセスに直接パイプすることができます。

./my_perl_script.pl | my_other_script

これは、これまでに使用したすべてのOS(Windows、Linux、OS X、BSD)で機能します。

于 2012-06-20T15:55:30.693 に答える
0

更新:さまざまなサブタスク(特に処理中のサブタスク)を抽象化する概念を説明するために、元の回答のコードへのリンクを残します。ただし、入力ファイルで何を期待できるかがわかっている場合は、問題をはるかに簡単に解決できます。

use warnings;
use strict;

my $lengths_filename = 'Transcriptlength.fa';
my $counts_filename  = 'Quadcount.AllGtranscripts.fa';

my %sequence;   # it will be the basic data repository

local $/ = ''; 
# ...by this we ensure that files will be read by logical blocks instead of lines. 
# Might need some tweaking, if 'empty line' in your sample is not really empty.

# we start processing from 'counts' file, as only those records present in it
# should actually be in our output:
open my $cfh, '<', $counts_filename 
  or die $!, "\n";
while (<$cfh>) {
  # each logical block consists of two parts, divided by whitespace
  my ($name, $count) = split; 

  # here goes magic: we simultaneously create a new record in our repository...
  # ... and set its 'count' property to the value, extracted from the scanned fileblock
  $sequence{$name}{count} = $count;
}
close $cfh;

# now we go for lengths, approach is almost the same
open my $lfh, '<', $lengths_filename or die $!, "\n";
while (<$lfh>) {
  my ($name, $length) = split;

  # here we check that the sequence was in 'counts' file
  if (exists $sequence{$name}) { 
    $sequence{$name}{length} = $length;
  } 
}
close $lfh;

# and now the output block: it's mostly the same as in the original answer:
for my $name (sort keys %sequence) {
  print "$name, $sequence{$name}{count}, $sequence{$name}{length}", "\n";
}

これがどのように機能するかを説明する別のコードパッドです。奇妙なことは気にしないでください__DATA__。これはこの特定のバージョンのプログラム専用です(__DATA__コードパッドでは外部ソースを使用できないため、セクションを使用するとファイルからの読み取りをシミュレートできます)。

于 2012-06-20T16:30:15.343 に答える
0

これ

$ data = join(''、@ data); #文字列に変換
@ data2 = split('\ n'、$ data); #改行に沿って爆発する

あなたが思うようにあなたの配列を作成しません。それはあなたが始めた線の構造を再現するだけです。「、」コンマで分割するつもりだったと思います。デバッグツールを使用します。少なくとも、このような印刷ブロックを挿入します

print join( ":"、@ data2);

アレイに実際に何があるかを確認します。

次の行に進む前に、各行を機能させてください。次に、行が機能しない理由がわからない場合は、ここに質問を投稿できます。

現状では、アイデアが不完全であるため、コードで何を言おうとしていたかを判断するのは困難です。

于 2012-06-20T16:53:20.423 に答える