所以我有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...]
做同样的事情,那么我可以将foo1
和foo2
加起来得到[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分钟。
答案 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())]
除非您的文件中包含不同数量的列,否则应该没有太多问题。
如果您的文件非常大,内存可能会成为一个问题。在这种情况下,您可能希望通过块工作:从第一个文件中只读取几百行并将它们存储在列表中,然后按照您在第一个文件中读取的行数进行描述,然后重新开始另外几百行...
修改强>
考虑到您在编辑中描述的计算时间,此解决方案显然不是最理想的。您无法在内存中加载整个文件,因此您必须按块工作。遵循工作流程可能更好:
foo1
。ndarray
并将此数组追加到foo1
。此时,您应该有一个foo1
列表,其中包含与您定义的块一样多的条目,每个条目都是一个numpy数组。现在
foo2_tmp
foo2_tmp
添加到foo_1[0]
,到位:即foo_1[0] += foo2_tmp
。请记住,foo_1[0]
是您的第一个块,ndarray
。foo_1
答案 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]