0

我正在尝试优化一些代码以更快地运行。对于此文本文件矩阵:

TAG, DESC, ID1, ID2, ID3, ID4, 
1, "details", 0, 1, NA, 1, 2
2, "details", 2, 1, NA, 0, 1
3, "details", 1, NA, NA, 0, 2
...

这是一个包含约 10,000 列和约 2M 行的大文件。我想做的是计算所有 ID 的总和(TAG=1 时为 4)和给定最大值为 2 的频率(因此 4/8 = 0.5),然后将这些值附加为新列。NA 缺少数据并且实际上为零。此代码有效,但速度很慢:

tab_dict =csv.DictReader(open(path), delimiter=",") 
tab_reader = [row for row in tab_dict]

for t in tab_reader:
    idlist = [i for i in t.keys()] 
    idlist.remove('TAG')  #exclude columns that do not contain numbers for summing
    idlist.remove('DESC')
    rowsum = 0
    for i in idlist:
        try: rowsum+= int(t[i]) #try/except to handle "NA"s
        except: TypeError
    t["ROWSUM"] = rowsum  # create the new columns
    t["ROWFREQ"] = float(rowsum)/ float(2*len(idlist))

关于如何加快速度的任何建议?谢谢

4

2 回答 2

2

是否将整个文件读入tab_reader列表以便您可以随时修改它?如果可能的话,这是你应该避免的。由于阅读器是一个迭代器,如果您以后的处理不需要整个文件都在内存中,那么最好逐行写入修改后的输出。

这个版本仍然使用字典阅读器,但更多的内置工具,应该更快:

ignored_keys = frozenset(('TAG', 'DESC'))   
desired_keys = [key for key in tab_dict.fieldnames if key not in ignored_keys]
frequency_divisor = float(2*len(desired_keys))
for t in tab_reader:
    rowsum = sum((int(t[key]) for key in desired_keys if t[key] != 'NA'))
    rowfreq = float(rowsum) / frequency_divisor
    t["ROWSUM"] = rowsum
    t["ROWFREQ"] = rowfreq

我认为您会看到使用csv.reader实例而不是DictReader预先计算所需索引列表而不是键的额外改进。或者,当然,如果 'TAG' 和 'DESC' 总是前两个:

   rowsum = sum((int(x) for x in t[2:] if x != 'NA'))
于 2013-09-13T14:55:09.960 回答
2

其一,您循环遍历数据两次,一次是创建 tab_reader,一次是对所有值求和。其次,您可能想放弃您的 DictReader 并简单地自己循环文件。此外,使用内置函数会加快速度。

from __future__ import division # to use float division

for line in open(path):
    ids = line.split(',')[2:]
    ids = [int(id) if id != 'NA' else 0 for id in ids]
    rowsum = sum(ids)
    rowfreq = rowsum / 2 * len(ids)
于 2013-09-13T14:55:19.473 回答