在python中逐行包含两个包含浮点数的文本文件

时间:2012-09-20 12:00:04

标签: python text gzip sum text-files

所以我有4,000个大的gzip压缩文本文件。由于它们的大小,我需要逐行加总。理想情况下(我认为)我想打开一个然后循环其他3,999并简单地将它们的值汇总到第一个。这是我到目前为止所拥有的

with gzip.open('foo1.asc.gz','r') as f:
    for i in xrange(6):  # Header is 6 lines
        f.next()
    line = f.readline()
    foo1=map(float, line.strip().split())
    print foo1

这将返回我需要为foo1求和的值;因此输出是逗号分隔的浮点列表(例如,[1.2, 6.0, 9.3...])。

为了清楚起见,如果我对foo2 = [1.2, 6.0...]做同样的事情,那么我可以将foo1foo2加起来得到[2.4, 12.0...],覆盖foo1。然后继续遍历每一行以覆盖foo1。当然,这需要循环4k文件。

如果有人可以帮助我完成2循环和/或总和操作,我将非常感激。

*更新 * 现在使用以下代码:

foo1=[]
with gzip.open('foo1','r') as f:
    skip_header()
    for line in f:
        foo1.append([float(i) for i in line.strip().split()])


with gzip.open('foo2','r') as f:
    skip_header()
    for (i, line) in enumerate(f):
        foo1[i] = [j + float(k) for (j, k) in zip(foo1[i], line.strip().split())]

哪个有效,但是很好。我输入大约11分钟。

2 个答案:

答案 0 :(得分:2)

你可能需要在内存中保留一个列表,一个列出第一个文件的行。

with gzip.open(...) as f:
    skip_header()
    foo1 = [[float(i) for i in line.strip().split()] for line in f]
  • 注意:在这里,我们立即构建列表,这意味着f的整个内容都会加载到内存中。如果文件很大,那可能是个问题。在这种情况下,只需:

    foo1 = []
    with gzip.open(...) as f:
        skip_header()
        for line in f:
            foo1.append([float(i) for i in line.strip().split()])
    

然后,您可以打开第二个文件,在其行上循环并将值添加到foo的相应条目中:

with gzip.open(file2) as f:
    skip_header()
    for (i, line) in enumerate(f):
        foo1[i] = [j + float(k) for (j, k) in zip(foo1[i], line.strip().split())]

除非您的文件中包含不同数量的列,否则应该没有太多问题。

如果您的文件非常大,内存可能会成为一个问题。在这种情况下,您可能希望通过块工作:从第一个文件中只读取几百行并将它们存储在列表中,然后按照您在第一个文件中读取的行数进行描述,然后重新开始另外几百行...

修改

考虑到您在编辑中描述的计算时间,此解决方案显然不是最理想的。您无法在内存中加载整个文件,因此您必须按块工作。遵循工作流程可能更好:

  1. 创建一个空列表foo1
  2. 打开第一个文件,读取给定的一些行,将这些行转换为numpy ndarray并将此数组追加到foo1
  3. 对另一行行重复第二步,直到您读取整个输入文件
  4. 此时,您应该有一个foo1列表,其中包含与您定义的块一样多的条目,每个条目都是一个numpy数组。现在

    1. 打开第二个文件,读取与步骤#2中一样多的行,将这些行转换为numpy数组foo2_tmp
    2. foo2_tmp添加到foo_1[0]到位:即foo_1[0] += foo2_tmp。请记住,foo_1[0]是您的第一个块,ndarray
    3. 对另一行行重复步骤5.并更新foo_1
    4. 中的相应条目
    5. 重复步骤6.直到您阅读第二个文件
    6. 重复步骤4.-7。为您的第三个文件

答案 1 :(得分:0)

这是未经测试的。请注意,尝试一次打开4,000个文件句柄可能效率不高(甚至可能不允许),因此一次接近文件是最实用的。下面使用defaultdict,它允许每个文件中的行数不匹配,但仍然能够对重叠的行号进行求和。

from itertools import islice
from collections import defaultdict
from glob import iglob

def sum_file(filename, dd):
    file_total = 0.0
    with gzip.open(filename) as fin:
        for lineno, line in enumerate(islice(fin, 6, None)): # skip headers
            row_total = map(float, line.split())                
            dd[lineno] += row_total
            file_total += row_total
    return file_total


dd = defaultdict(float)
for filename in iglob('foo*.asc.gz'):
    print 'processed', filename, 'which had a total of', sum_file(filename, dd)

print 'There were', len(dd), 'rows in total'
for lineno in sorted(dd.keys()):
    print lineno, 'had a total of', dd[lineno]