python结合每一行:使脚本更有效

时间:2016-05-31 15:05:02

标签: python performance parsing

我很抱歉这个问题基本如何。

目标:这是我从软件程序中输出的:

1   590 SC  1.000   LEU2_YEAST  100%
1   590 EC  1.000   LEU2_ECOLI  100%
2   467 SC  1.000   FADH_YEAST  100%
2   467 EC  1.000   ADH3_ECOLI  100%
3   463 SC  1.000   6PG1_YEAST  100%
3   463 SC  0.816   6PG2_YEAST
3   463 EC  1.000   6PGD_ECOLI  100%
3   463 EC  0.903   6PG9_ECOLI
4   446 SC  1.000   YME1_YEAST  59%
4   446 EC  1.000   FTSH_ECOLI  100%
5   411 SC  1.000   ADH4_YEAST  100%
5   411 EC  1.000   ADH2_ECOLI  99%
8   256 SC  1.000   ATM1_YEAST  100%
8   256 EC  1.000   HLYB_ECOLI  99%
8   256 EC  0.987   HLY2_ECOLI
9   252 SC  1.000   MDL2_YEAST  100%
9   252 SC  0.203   MDL1_YEAST
9   252 EC  1.000   MSBA_ECOLI  99%

对于那些具有生物学背景的人,我只想提取相应的最佳命中率。对于那些具有非生物学背景的人,我想提取基因对,只要第一列中的数字只出现两次。

例如,我们可以看到数字1在文件的第一列中出现两次:

 1  590 SC  1.000   LEU2_YEAST  100%
 1  590 EC  1.000   LEU2_ECOLI  100%

但是数字3出现4次出现在文件的第一列:

3   463 SC  1.000   6PG1_YEAST  100%
3   463 SC  0.816   6PG2_YEAST
3   463 EC  1.000   6PGD_ECOLI  100%
3   463 EC  0.903   6PG9_ECOLI

因此,对于此示例文件,输出将如下所示:

LEU2_YEAST LEU2_ECOLI
FADH_YEAST ADH3_ECOLI
YME1_YEAST FTSH_ECOLI
ADH4_YEAST ADH2_ECOLI

因为这些是文件中唯一的四对行。

这是我的代码:

import sys
Dict1 = {}
for line in open(sys.argv[1]):
    line = line.strip().split()
    if line[0] not in Dict1.keys():
        Dict1[line[0]] = [line[4]] 
    elif line[0] in Dict1.keys():
        Dict1[line[0]].append(line[4])

for i in Dict1.values():
    if len(i) == 2:
        print i[0] + "\t" + i[1] 

这很有效,它打印的输出是:

LEU2_YEAST  LEU2_ECOLI
FADH_YEAST  ADH3_ECOLI
ADH4_YEAST  ADH2_ECOLI
YME1_YEAST  FTSH_ECOLI

我只是好奇其他人会怎么做?实际上,我的实际数据集将有数千行,所以我想知道这样做的效率是否更高(在时间或内存方面)?或者人们如何加入"支票"确保号码只出现两次?在这个阶段,我掌握了python的基础知识,所以我正在研究如何更好地设计代码。

2 个答案:

答案 0 :(得分:1)

可能的改进是将if line[0] not in Dict1.keys()更改为if line[0] not in Dict1,因为not in Dict1.keys()是O(n)操作,而not in Dict是O(1)。

我不确定真正的性能提升。您应该使用time来计算出来。

答案 1 :(得分:1)

如果您的文件按第一行中的数字排序,则可以使用itertools.groupby

from itertools import groupby
import operator

with open(sys.argv[1]) as infile:
    # split lines and group them by the number in the first column
    groups= groupby([line.strip().split() for line in infile], operator.itemgetter(0))
# convert groups to lists and discard keys
groups= [list(lines) for _, lines in groups]
# discard groups that don't have 2 items and format the output
groups= ['%s\t%s'%(lines[0][4],lines[1][4]) for lines in groups if len(lines)==2]
# alternatively you can use
#   groups= ['\t'.join(zip(*lines)[4]) for lines in groups if len(lines)==2]

print '\n'.join(groups)