0

我有以下格式的数据集:

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

真实的数据比这大得多,扩展到数百万行和大约一千列。我的最终目标是转置这个怪物并将结果输出到一个文本文件(或 CSV 文件或其他文件,无所谓)中。

我需要将数据逐个输入我的计算机,以免内存超载。我逐行读取 CSV 文件,然后将其转置,然后写入文件。然后,我循环返回并重复这些步骤,并在执行过程中附加到文本文件中。

问题当然是如果结果是原始数据文件的转置,我应该逐列而不是逐行附加文本文件。但一位朋友告诉我,这在 Perl 代码中是不可行的。我想知道我是否可以逐列读取数据。有没有类似的东西,比如我在原始代码中使用的getline方法

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

可以返回列而不是行?cut如果不需要将整个数据加载到内存中,则首选类似于 Unix命令的命令。

4

2 回答 2

1

CSV 只是一个文本文件;它由一大长行的文本字符组成,因此不能随机访问列。理想情况下,您会将 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);
}

最后,每列将在其自己的文本文件中打印为一行。不要忘记关闭所有文件,然后再次打开它们以供阅读,然后一次将它们写入一个输出文件。我的猜测是这会很慢,但足够快以执行数百万行,只要您不必经常这样做。而且它不会面临内存限制。

于 2012-08-13T15:20:28.013 回答
0

如果文件不适合您的计算机内存,您的程序必须多次读取它。没有其他办法了。

可能有一些模块掩盖或隐藏了这一事实——比如 DBD::CSV——但那些只是在幕后做同样的工作。

于 2012-08-13T15:04:01.750 回答