我想知道在python中解析长格式数据的最佳方法是什么。我之前在R中做过这样的任务,但它确实需要很长时间,因为我的文件可以超过1 GB。这是一些虚拟数据:
Sequence Position Strand Score
Gene1 0 + 1
Gene1 1 + 0.25
Gene1 0 - 1
Gene1 1 - 0.5
Gene2 0 + 0
Gene2 1 + 0.1
Gene2 0 - 0
Gene2 1 - 0.5
但是我希望能够以广泛的形式将它与每个位置的分数相加。这是我希望的输出:
Sequence 0 1
Gene1 2 0.75
Gene2 0 0.6
任何有关如何从概念上解决此类问题的帮助都会非常有用。
答案 0 :(得分:7)
这两种解决方案似乎都有点矫枉过正,你可以用一个单行的大熊猫来做这件事:
In [7]: df
Out[7]:
Sequence Position Strand Score
0 Gene1 0 + 1.00
1 Gene1 1 + 0.25
2 Gene1 0 - 1.00
3 Gene1 1 - 0.50
4 Gene2 0 + 0.00
5 Gene2 1 + 0.10
6 Gene2 0 - 0.00
7 Gene2 1 - 0.50
In [8]: df.groupby(['Sequence', 'Position']).Score.sum().unstack('Position')
Out[8]:
Position 0 1
Sequence
Gene1 2 0.75
Gene2 0 0.60
如果您无法将文件加载到内存中,那么其他答案中的核心外解决方案也会起作用。
答案 1 :(得分:0)
解决此类问题的简便方法是使用dict
或其中一对,或甚至一对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中重写你的逻辑并使用{{3}}模块为你执行它
如果您的数据库太大而SQLite无法处理它,您可以查看MySQL或其他外部数据库引擎。