得到不匹配的行号python

时间:2014-10-06 04:17:15

标签: python enumerate

您好我在python中编写了一个简单的代码来执行以下操作:

我有两个总结基因组数据的文件。第一个文件有我想要删除的基因座的名称,它看起来像这样

File_1:

R000002
R000003
R000006

第二个文件包含我所有基因座的名称和位置,如下所示:

File_2:

R000001 1
R000001 2
R000001 3
R000002 10
R000002 2
R000002 3
R000003 20
R000003 3
R000004 1
R000004 20
R000004 4
R000005 2
R000005 3
R000006 10
R000006 11
R000006 123

我想要做的是从File2获取不在File1中的所有相应的基因座编号,因此最终结果应如下所示:

结果:

1
2
3
9
10
11
12
13

我编写了以下简单代码并完成了工作

#!/usr/bin/env python

import sys

File1 = sys.argv[1]
File2 = sys.argv[2]

F1 = open(File1).readlines()
F2 = open(File2).readlines()
F3 = open(File2 + '.np', 'w')
Loci = []

for line in F1:
        Loci.append(line.strip())

for x, y in enumerate(F2):
        y2 = y.strip().split()
        if y2[0] not in Loci:
                F3.write(str(x+1) + '\n')

然而,当我在我的真实数据集上运行它时,第一个文件有58470行,第二个文件有12881010行,它似乎需要永远。我猜测瓶颈在于

if y2[0] not in Loci:

代码必须重复搜索整个File_2的部分,但我找不到更快的解决方案。

任何人都可以帮助我,并展示更多的pythonic做事方式。

提前致谢

2 个答案:

答案 0 :(得分:2)

这里有一些稍微多一些Pythonic代码,它们不关心你的文件是否有序。我更愿意将所有内容打印出来并将其重定向到文件./myscript.py > outfile.txt,但您也可以传入另一个文件名并写入。

#!/usr/bin/env python
import sys

ignore_f = sys.argv[1]
loci_f = sys.argv[2]

with open(ignore_f) as f:
    ignore = set(x.strip() for x in f)

with open(loci_f) as f:
    for n, line in enumerate(f, start=1):
        if line.split()[0] not in ignore:
            print n

在列表中搜索某些内容是O(n),而对于一个集合只需要O(1)。如果订单无关紧要且您有独特之处,请在列表上使用set。虽然这不是最佳的,但它应该是O(n)而不是O(n×m),就像你的代码一样。

你也没有关闭你的文件,这些文件在阅读时并不是那么重要,但在编写时却是。我使用上下文管理器(with),所以Python为我做了这个。

样式方式,使用描述性变量名称。并且避免使用UpperCase个名称,这些名称通常用于类(请参阅PEP-8)。

如果您的文件是订购的,您可以一起单步执行,忽略基因座名称相同的行,然后当它们不同时,在忽略文件中再执行一步并重新检查。

答案 1 :(得分:0)

为了更有效地搜索匹配项,您只需使用set代替list

Loci = set()

for line in F1:
    Loci.add(line.strip())

其余部分应该相同,但速度更快。

更有效的方法是以一种锁步方式向下浏览文件,因为它们都已经排序,但这需要更多代码,而且可能不是必需的。