Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 如何逐列读取CSV文件以进行转置?_Perl_Csv_Large Files_Transpose - Fatal编程技术网

Perl 如何逐列读取CSV文件以进行转置?

Perl 如何逐列读取CSV文件以进行转置?,perl,csv,large-files,transpose,Perl,Csv,Large Files,Transpose,我有以下格式的数据集: snp,T2DG0200001,T2DG0200002,T2DG0200003,T2DG0200004 3_60162,AA,AA,AA,AA 3_61495,AA,AA,GA,GA 3_61466,GG,GG,CG,CG 实际数据要比这大得多,可以扩展到数百万行和大约1000列。我的最终目标是转置这个怪物,并将结果输出到一个文本文件(或CSV文件或其他文件,无所谓) 我需要把数据一块一块地输入我的电脑,以免我的内存过载。我逐行读取CSV文件,然后将其转置,然后写入文件

我有以下格式的数据集:

snp,T2DG0200001,T2DG0200002,T2DG0200003,T2DG0200004
3_60162,AA,AA,AA,AA
3_61495,AA,AA,GA,GA
3_61466,GG,GG,CG,CG
实际数据要比这大得多,可以扩展到数百万行和大约1000列。我的最终目标是转置这个怪物,并将结果输出到一个文本文件(或CSV文件或其他文件,无所谓)

我需要把数据一块一块地输入我的电脑,以免我的内存过载。我逐行读取CSV文件,然后将其转置,然后写入文件。然后我循环并重复这些步骤,并在执行过程中附加到文本文件

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

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

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

如果文件不适合计算机内存,则程序必须多次读取。这是没有办法的


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

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);
}
my@filehandles;
我的$line=0;
while(my$row=$csv->getline($fh))
{
#为每列打开一个输出文件!
if(未定义$filehandles[0])
{
对于(0..$#$行)
{
本地$handle;
打开$handle,“>column\u$\ ux.txt”或死“Oops!”;
推@filehandles,$handle;
}
}
#将每列打印到其各自的输出文件中。
对于(0..$#$行)
{
打印$filehandles[$\]$row->[$\].“,”;
}
#这将需要很长时间,所以要显示一些生命迹象。
如果($line++%1000)==0,则打印“.”;
}

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

反省一下,如果有数千列,这可能不是最好的方法。您可能会遇到打开文件数量的限制。如果这导致打开的文件句柄过多,您可以将其修改为分块工作。比如说,将前500列写入文本文件,然后将下500列写入文本文件,依此类推,直到完成为止。这样,您只需读取输入文件几次,而不是数千次。最后一件事:对于一个不那么麻烦的解决方案,有许多Perl模块实现了一个简单的数据库。一个例子是:对于打开的句柄太多的问题,通常的解决方法是,与数据库模块相比,只需要很少的代码更改。-1对于基本上重新发布,而不解释您收到的答案不合适的原因。-1当然有一种解决方法:,而不是逐列;那么只需要一个通行证。最终的结果是一样的。一般来说,“你不能在Perl中这么做”的答案注定会被推翻。