我正在尝试优化某些代码以更快地运行。对于此文本文件矩阵:
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))
有关如何加快速度的任何建议?感谢
答案 0 :(得分:2)
是否将整个文件读入tab_reader
列表,以便您可以随时修改它?如果可能的话,这是你应该避免的。由于读者是一个迭代器,如果你以后的处理不需要整个文件在内存中,那么逐行编写修改后的输出会更好。
这个版本仍然使用dictreader,但更多的内置工具应该更快:
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'))
答案 1 :(得分: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)