您好我在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做事方式。
提前致谢
答案 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())
其余部分应该相同,但速度更快。
更有效的方法是以一种锁步方式向下浏览文件,因为它们都已经排序,但这需要更多代码,而且可能不是必需的。