0

次の形式のデータセットがあります。

snp,T2DG0200001,T2DG0200002,T2DG0200003,T2DG0200004
3_60162,AA,AA,AA,AA
3_61495,AA,AA,GA,GA
3_61466,GG,GG,CG,CG

実際のデータはこれよりはるかに大きく、数百万行と約1,000列に拡張されます。私の最終的な目標は、この怪物を転置し、結果をテキストファイル(またはCSVファイルなど)で出力することです。

メモリが過負荷にならないように、データを1つずつコンピュータにフィードする必要があります。CSVファイルを1行ずつ読み取り、転置してファイルに書き込みます。次に、ループバックして手順を繰り返し、テキストファイルに追加します。

もちろん問題は、結果が元のデータファイルの転置である場合、テキストファイルを行ではなくごとに追加することになっていることです。しかし、友人は、Perlコードでは実行不可能だと私に言いました。データを列ごとに読み取ることができるかどうか疑問に思っています。元のコードで使用したgetline方法など、似たようなものはありますか?

while (my $row = $csv->getline ($fh)) {

行の代わりに列を返すことができますか?cutデータ全体をメモリにロードする必要がない場合は、Unixコマンドに似たものが望ましいでしょう。

4

2 に答える 2

1

CSVは単なるテキストファイルです。テキスト文字の1つの大きな長い行で構成されているため、列にランダムにアクセスすることはできません。理想的には、CSVをデータベースに入れて、これを直接実行できるようにします。

ただし、それを除けば、Perlで少し巧妙にこれを行うことができると思います。私のアプローチは次のようになります。

my @filehandles;
my $line = 0;    

while (my $row = $csv->getline ($fh)<FILE>)
{
   #open an output file for each column!
   if (not defined $filehandles[0])
   {
       for (0..$#$row)
       {
           local $handle;
           open $handle, ">column_$_.txt" or die "Oops!";
           push @filehandles, $handle;
       }
   }

   #print each column to its respective output file.
   for (0..$#$row)
   {
       print $filehandles[$_] $row->[$_] . ",";
   }

   #This is going to take a LONG time, so show some sign of life.
   print '.' if (($line++ % 1000) == 0);
}

最後に、各列は独自のテキストファイルに行として出力されます。すべてのファイルを閉じてから、もう一度開いて読み取り、1つずつ1つの出力ファイルに書き込むことを忘れないでください。私の推測では、これは遅いですが、頻繁に実行する必要がない限り、数百万行を実行するのに十分な速度です。そして、それはメモリの制限に直面しません。

于 2012-08-13T15:20:28.013 に答える
0

ファイルがコンピュータのメモリに収まらない場合、プログラムはファイルを複数回読み取る必要があります。それを回避する方法はありません。

DBD :: CSVのように、この事実を覆い隠したり隠したりするモジュールがあるかもしれませんが、それらは舞台裏で同じ作業を行うだけです。

于 2012-08-13T15:04:01.750 に答える