解决此类问题的简单方法是使用 adict
或一对,甚至一对collections.Counter
s:
positions, scores = Counter(), Counter()
for sequence, position, strand, score in reader:
positions[sequence] += position
scores[sequence] += scores
for sequence in positions:
writer.writerow(sequence, positions[sequence], scores[sequence])
问题是这可能太大而无法放入内存。
我当然会先试试看。1GB 的输入文件并不意味着您需要 1GB 的内存。请记住,您只跟踪每个不同基因的总和,而不是输入文件中每一行的总和。在您的示例中,这意味着八个值中只有两个基因。
但是如果你不能把它放在内存中,你需要一个数据库。在这里,您真的只需要一个简单的键值数据库,它的作用类似于dict
,而不是花哨的东西。Python 内置了它,如dbm
.
例如(写得过于冗长以确保它易于理解):
import csv
import shelve
with dbm.open('p.db', 'w') as positions, dbm.open('s.db', 'w') as scores:
with open('input.tsv') as infile:
for row in csv.DictReader(infile, delimiter='\t'):
sequence = row['Sequence']
position = row['Position']
score = row['Score']
old_position = positions.get(sequence, '0')
positions[sequence] = str(int(old_position) + int(position))
old_score = scores.get(sequence, '0')
scores[sequence] = str(int(old_score) + int(score))
with open('output.tsv', 'w') as outfile:
writer = csv.writer(outfile, delimiter='\t')
for sequence in positions:
writer.writerow((sequence, positions[sequence], scores[sequence]))
如果您需要做一些更复杂的事情,而简单的键值数据库将无法工作,那么您可能需要用 SQL 重写您的逻辑并使用该sqlite3
模块为您执行它。
如果你的数据库太大以至于 SQLite 无法处理,你可以看看 MySQL 或其他外部数据库引擎。