我有以下格式的数据集:
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
method
while (my $row = $csv->getline ($fh)) {
可以返回列而不是行吗?如果不需要将整个数据加载到内存中,那么类似于Unix cut
命令的东西将是首选。
答案 0 :(得分: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);
}
最后,每列将在其自己的文本文件中作为一行打印。不要忘记关闭所有文件,然后再次打开它们进行读取,然后一次将它们写入一个输出文件中。我的猜测是,这会很慢,但速度足以达到数百万行,只要你不经常这样做。并且它不会面临记忆限制。
答案 1 :(得分:0)
如果文件不适合您的计算机内存,您的程序必须多次读取它。没有其他办法了。
可能有些模块会隐藏或隐藏这个事实 - 比如DBD :: CSV - 但那些只是在幕后做同样的工作。