使用 python 减少表格爆炸输出文件中的命中数
Use python to reduce number of hits in tabular blast output file
我有一个很大的表格格式的blast文件,目标序列的数量没有限制,所以解析需要很长时间。我想将每个查询序列的命中数减少到前 10 个。
我的 python 是基本的,但这是我目前所拥有的
import sys
blastfile = open(sys.argv[1],"r")
column1list=[]
for line in blastfile:
b = line.split()[0]
column1list.append(b)
uniqcolumn1 = list(set(column1list))
counter = 0
for val in uniqcolumn1:
#print val
for line in blastfile:
#print line
while counter <= 10:
if line.startswith(val):
print line
counter =+ 1
这里是blast输出文件的一行示例,查询序列的标题在第一列,在本例中'c8208_g1_i2'
c8208_g1_i2 gi|851252702|ref|WP_048131971.1| 79.30 797 165 0 4881 2491 1 797 0.0 1336 acetyl-CoA decarbonylase/synthase complex subunit alpha [Methanosaeta concilii]
我认为代码的第一部分工作正常,直到 '
uniqcolumn1 = list(set(column1list))',那么我无法打印以列表中的每个字符串开头的前十行。
此 one-pass 版本按标题在文件中出现的顺序打印每个标题的前 10 个:
import sys
NUM_TO_PRINT=10 # good practice - use names rather than raw numbers
blastfile = open(sys.argv[1],"r")
titles={}; # an empty dictionary.
# This will map titles to counts of how many times a line with that title
# has been printed.
for line in blastfile:
title = line.split()[0]; # assuming the title is space-delimited, and that the line is not empty
num_printed = titles.get(title, 0); # 0 is the default
if num_printed<NUM_TO_PRINT:
print line, # comma because _line_ already has a newline - without the comma, you get a blank line after every printed line
num_printed += 1
titles[title] = num_printed # save where we are
这里的问题似乎是您对文件对象进行了两次迭代。在 Python 中,文件对象的工作方式很像读取每一行的指针。如果你不把指针移回去,它就没有什么可读的了。
您需要做的是使用 .seek
函数将此指针移回起点。例如,假设您有 file_to_read.txt
和 python_script.py
.
file_to_read.txt
Hello! My name is Bob and I can't think of anything to
put in this file so I'm blabbering on about nonsense
in hopes that you won't realise that this text is not
important but the code in the actually file, though I
think that you wouldn't mind reading this long file.
python_script.py
f = open("file_to_read.txt", "r")
for line in f: print line
for line in f: print line
如果您要 运行 此代码(并且不会出现关于目录的错误),您将只打印一次 file_to_read.txt
。为了解决这个问题,你可以在阅读之间添加一个 f.seek(0, 0)
。例如:
f = open("file_to_read.txt", "r")
for line in f: print line
f.seek(0, 0)
for lien in f: print line
现在,回到您的上下文,您可以看到这如何适用于您的代码:
import sys
# Here is your reading of file
blastfile = open(sys.argv[1],"r")
column1list = []
# Here is the first time you read the file
for line in blastfile:
b = line.split()[0]
column1list.append(b)
# Add a line to move back to the start before the
# next reading
blastfile.seek(0, 0)
uniqcolumn1 = list(set(column1list))
for val in uniqcolumn1:
# Move the counter inside to refresh it after every iteration
counter = 0
# Here is the second time you read your file
for line in blastfile:
while counter <= 10:
if line.startswith(val):
print line
counter += 1
# Since you are going to read the file the next iteration,
# .seek the file
blastfile.seek(0, 0)
编辑
这是代码的后半部分,已修复。您可以这样做:
for val in uniqcolumn1:
# Move the counter in
counter = 0
# Move the while loop out
while counter <= 10:
for line in blastfile:
if line.startswith(val):
print line,
counter += 1
blastfile.seek(0, 0)
这样做的好处是 for 循环提前终止,它不会读取整个文件。
另一种方法是使用这个:
for val in uniqcolumn1:
# Move counter in
counter = 0
# Remove while statement
for line in blastfile:
# Add additional condition to if statement
if line.startswith(val) and counter <= 10:
print line,
counter += 1
elif counter > 10:
break
blastfile.seek(0, 0)
这样做的好处是看起来比较简单
我有一个很大的表格格式的blast文件,目标序列的数量没有限制,所以解析需要很长时间。我想将每个查询序列的命中数减少到前 10 个。 我的 python 是基本的,但这是我目前所拥有的
import sys
blastfile = open(sys.argv[1],"r")
column1list=[]
for line in blastfile:
b = line.split()[0]
column1list.append(b)
uniqcolumn1 = list(set(column1list))
counter = 0
for val in uniqcolumn1:
#print val
for line in blastfile:
#print line
while counter <= 10:
if line.startswith(val):
print line
counter =+ 1
这里是blast输出文件的一行示例,查询序列的标题在第一列,在本例中'c8208_g1_i2'
c8208_g1_i2 gi|851252702|ref|WP_048131971.1| 79.30 797 165 0 4881 2491 1 797 0.0 1336 acetyl-CoA decarbonylase/synthase complex subunit alpha [Methanosaeta concilii]
我认为代码的第一部分工作正常,直到 ' uniqcolumn1 = list(set(column1list))',那么我无法打印以列表中的每个字符串开头的前十行。
此 one-pass 版本按标题在文件中出现的顺序打印每个标题的前 10 个:
import sys
NUM_TO_PRINT=10 # good practice - use names rather than raw numbers
blastfile = open(sys.argv[1],"r")
titles={}; # an empty dictionary.
# This will map titles to counts of how many times a line with that title
# has been printed.
for line in blastfile:
title = line.split()[0]; # assuming the title is space-delimited, and that the line is not empty
num_printed = titles.get(title, 0); # 0 is the default
if num_printed<NUM_TO_PRINT:
print line, # comma because _line_ already has a newline - without the comma, you get a blank line after every printed line
num_printed += 1
titles[title] = num_printed # save where we are
这里的问题似乎是您对文件对象进行了两次迭代。在 Python 中,文件对象的工作方式很像读取每一行的指针。如果你不把指针移回去,它就没有什么可读的了。
您需要做的是使用 .seek
函数将此指针移回起点。例如,假设您有 file_to_read.txt
和 python_script.py
.
file_to_read.txt
Hello! My name is Bob and I can't think of anything to
put in this file so I'm blabbering on about nonsense
in hopes that you won't realise that this text is not
important but the code in the actually file, though I
think that you wouldn't mind reading this long file.
python_script.py
f = open("file_to_read.txt", "r")
for line in f: print line
for line in f: print line
如果您要 运行 此代码(并且不会出现关于目录的错误),您将只打印一次 file_to_read.txt
。为了解决这个问题,你可以在阅读之间添加一个 f.seek(0, 0)
。例如:
f = open("file_to_read.txt", "r")
for line in f: print line
f.seek(0, 0)
for lien in f: print line
现在,回到您的上下文,您可以看到这如何适用于您的代码:
import sys
# Here is your reading of file
blastfile = open(sys.argv[1],"r")
column1list = []
# Here is the first time you read the file
for line in blastfile:
b = line.split()[0]
column1list.append(b)
# Add a line to move back to the start before the
# next reading
blastfile.seek(0, 0)
uniqcolumn1 = list(set(column1list))
for val in uniqcolumn1:
# Move the counter inside to refresh it after every iteration
counter = 0
# Here is the second time you read your file
for line in blastfile:
while counter <= 10:
if line.startswith(val):
print line
counter += 1
# Since you are going to read the file the next iteration,
# .seek the file
blastfile.seek(0, 0)
编辑
这是代码的后半部分,已修复。您可以这样做:
for val in uniqcolumn1:
# Move the counter in
counter = 0
# Move the while loop out
while counter <= 10:
for line in blastfile:
if line.startswith(val):
print line,
counter += 1
blastfile.seek(0, 0)
这样做的好处是 for 循环提前终止,它不会读取整个文件。
另一种方法是使用这个:
for val in uniqcolumn1:
# Move counter in
counter = 0
# Remove while statement
for line in blastfile:
# Add additional condition to if statement
if line.startswith(val) and counter <= 10:
print line,
counter += 1
elif counter > 10:
break
blastfile.seek(0, 0)
这样做的好处是看起来比较简单