使用条件匹配一行中的多个模式
Using conditions to match multiple patterns within a line
我有一个这样的fasta文件:
myfasta.fasta
>1_CDS
AAAAATTTCTGGGCCCCGGGGG
AAATTATTA
>2_CDS
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>3_CDS
TTTGGGAATTAAACCCT
>4_CDS
TTTGGGAATTAAACCCT
>5_rRNA
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>6_tRNA
TTAAAAATTTCTGGGCCCCGGGAAAAAA
我有一个代码,我想使用它来根据具有匹配模式(如 'CDS'、'tRNA' 等)的 ID 来分隔序列。在下面的代码中,我尝试使用 startswith并且还匹配似乎不起作用的行中的模式。有人可以帮我如何在 python.
中查找两个条件吗
代码:python mycode.py myfasta.fasta
#!/usr/bin/env python
import sys
import os
myfasta = sys.argv[1]
fasta = open(myfasta)
for line in fasta:
if line.startswith('>') and 'CDS' in line:
print(line)
else:
print(line)
预期输出(如果我使用 CDS
):
>1_CDS
AAAAATTTCTGGGCCCCGGGGG
AAATTATTA
>2_CDS
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>3_CDS
TTTGGGAATTAAACCCT
>4_CDS
TTTGGGAATTAAACCCT
这是适合您的代码。如果一行有 CDS,它会打印该行和下一行。 strip()
在打印该行时删除结束符。
#!/usr/bin/env python
import sys
import os
myfasta = sys.argv[1]
flag = False
with open(myfasta) as fasta:
for line in fasta:
if line.startswith('>') and 'CDS' in line:
flag = True
elif line.startswith('>'):
flag = False
if flag:
print(line.strip())
编辑:可以去掉elif部分,如下代码:
#!/usr/bin/env python
import sys
import os
myfasta = sys.argv[1]
flag = False
with open(myfasta) as fasta:
for line in fasta:
if line.startswith('>'):
flag = 'CDS' in line
if flag:
print(line.strip())
这是你想要的吗?
#!/usr/bin/env python
import sys
import os
from collections import defaultdict
myfasta = sys.argv[1]
with open(myfasta) as fasta:
data = fasta.read().splitlines()
pattern_data = defaultdict(list)
index = 0
while index < len(data):
if data[index].startswith('>'):
start = data[index].index('_') + 1
key = data[index][start:]
pattern_data[key].append(data[index + 1])
index += 2
此时您可以随意对排序后的数据进行任何操作。
以上假定您解析的整个文件完全遵循上面显示的格式:1 行以“>”开头,id 是后面的单行。如果后面有多行,则代码需要稍作修改。
编辑:
我刚刚阅读了 fasta 文件。我现在知道,它们在被识别后实际上可能有超过一行的序列。所以上面的代码确实需要修改以考虑多行序列。更通用的做法如下:
#!/usr/bin/env python
import sys
import os
from collections import defaultdict
myfasta = sys.argv[1]
with open(myfasta) as fasta:
data = fasta.read().splitlines()
id_line_indices = [index for index, line in enumerate(data) if line.startswith('>')]
id_line_indices.append(len(data))
pattern_buckets = defaultdict(list)
i = 0
while i < len(id_line_indices) - 1:
start = data[id_line_indices[i]].index('_') + 1
key = data[id_line_indices[i]][start:]
sequence = [data[index] for index in range(id_line_indices[i] + 1, id_line_indices[i + 1])]
sequence = ''.join(sequence)
pattern_buckets[key].append(sequence)
i += 1
对于上面的数据集,仍然可以得到相同的结果。例如,
print(pattern_buckets['CDS'])
print(pattern_buckets['rRNA'])
会给你:
['AAAAATTTCTGGGCCCCGGGGG', 'TTAAAAATTTCTGGGCCCCGGGAAAAAA', 'TTTGGGAATTAAACCCT', 'TTTGGGAATTAAACCCT']
['TTAAAAATTTCTGGGCCCCGGGAAAAAA']
Maanijou 的回答很好。
另外,考虑使用迭代器的替代方案。
编辑:根据您的意见更新了代码
#!/usr/bin/env python
import sys
import os
myfasta = sys.argv[1]
fasta = open(myfasta, "r+")
file_contents = iter(fasta)
try:
print_flag = True
while True:
line = file_contents.next()
if line.startswith('>'):
if "CDS" in line:
print (line.strip())
print_flag = True
else:
print_flag = False
else:
if print_flag:
print (line.strip())
except StopIteration:
print ("Done")
fasta.close()
说明
file_contents = iter(fasta)
将可迭代文件 object 转换为一个迭代器,你可以简单地继续调用 next()
直到你 运行 没有东西可以读
为什么我不建议像其他一些答案那样调用 readlines
是因为有时 fasta 文件可能很大并且调用 readlines
会消耗大量内存。
如果一行满足您的搜索要求,您只需打印它和下一行,否则您只需阅读下一行而不做任何事情,
更新说明
- 由于文件模式,你得到了属性错误,我无法在本地重现它,但我认为用正确的模式打开文件应该可以解决这个问题
- 您现在说
CDS
的基因组序列可能不止 1 个更新了代码以打印文件中 1 CDS
header 的所有基因组序列
我用修改过的 fasta 文件测试过它
>1_CDS
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGCG
>2_CDS
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>3_CDS
TTTGGGAATTAAACCCT
>4_CDS
TTTGGGAATTAAACCCT
>5_rRNA
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>6_tRNA
TTAAAAATTTCTGGGCCCCGGGAAAAAA
而这个输出
python fasta.py fasta.fasta
>1_CDS
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGCG
>2_CDS
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>3_CDS
TTTGGGAATTAAACCCT
>4_CDS
TTTGGGAATTAAACCCT
Done
我有一个这样的fasta文件:
myfasta.fasta
>1_CDS
AAAAATTTCTGGGCCCCGGGGG
AAATTATTA
>2_CDS
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>3_CDS
TTTGGGAATTAAACCCT
>4_CDS
TTTGGGAATTAAACCCT
>5_rRNA
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>6_tRNA
TTAAAAATTTCTGGGCCCCGGGAAAAAA
我有一个代码,我想使用它来根据具有匹配模式(如 'CDS'、'tRNA' 等)的 ID 来分隔序列。在下面的代码中,我尝试使用 startswith并且还匹配似乎不起作用的行中的模式。有人可以帮我如何在 python.
中查找两个条件吗代码:python mycode.py myfasta.fasta
#!/usr/bin/env python
import sys
import os
myfasta = sys.argv[1]
fasta = open(myfasta)
for line in fasta:
if line.startswith('>') and 'CDS' in line:
print(line)
else:
print(line)
预期输出(如果我使用 CDS
):
>1_CDS
AAAAATTTCTGGGCCCCGGGGG
AAATTATTA
>2_CDS
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>3_CDS
TTTGGGAATTAAACCCT
>4_CDS
TTTGGGAATTAAACCCT
这是适合您的代码。如果一行有 CDS,它会打印该行和下一行。 strip()
在打印该行时删除结束符。
#!/usr/bin/env python
import sys
import os
myfasta = sys.argv[1]
flag = False
with open(myfasta) as fasta:
for line in fasta:
if line.startswith('>') and 'CDS' in line:
flag = True
elif line.startswith('>'):
flag = False
if flag:
print(line.strip())
编辑:可以去掉elif部分,如下代码:
#!/usr/bin/env python
import sys
import os
myfasta = sys.argv[1]
flag = False
with open(myfasta) as fasta:
for line in fasta:
if line.startswith('>'):
flag = 'CDS' in line
if flag:
print(line.strip())
这是你想要的吗?
#!/usr/bin/env python
import sys
import os
from collections import defaultdict
myfasta = sys.argv[1]
with open(myfasta) as fasta:
data = fasta.read().splitlines()
pattern_data = defaultdict(list)
index = 0
while index < len(data):
if data[index].startswith('>'):
start = data[index].index('_') + 1
key = data[index][start:]
pattern_data[key].append(data[index + 1])
index += 2
此时您可以随意对排序后的数据进行任何操作。
以上假定您解析的整个文件完全遵循上面显示的格式:1 行以“>”开头,id 是后面的单行。如果后面有多行,则代码需要稍作修改。
编辑: 我刚刚阅读了 fasta 文件。我现在知道,它们在被识别后实际上可能有超过一行的序列。所以上面的代码确实需要修改以考虑多行序列。更通用的做法如下:
#!/usr/bin/env python
import sys
import os
from collections import defaultdict
myfasta = sys.argv[1]
with open(myfasta) as fasta:
data = fasta.read().splitlines()
id_line_indices = [index for index, line in enumerate(data) if line.startswith('>')]
id_line_indices.append(len(data))
pattern_buckets = defaultdict(list)
i = 0
while i < len(id_line_indices) - 1:
start = data[id_line_indices[i]].index('_') + 1
key = data[id_line_indices[i]][start:]
sequence = [data[index] for index in range(id_line_indices[i] + 1, id_line_indices[i + 1])]
sequence = ''.join(sequence)
pattern_buckets[key].append(sequence)
i += 1
对于上面的数据集,仍然可以得到相同的结果。例如,
print(pattern_buckets['CDS'])
print(pattern_buckets['rRNA'])
会给你:
['AAAAATTTCTGGGCCCCGGGGG', 'TTAAAAATTTCTGGGCCCCGGGAAAAAA', 'TTTGGGAATTAAACCCT', 'TTTGGGAATTAAACCCT']
['TTAAAAATTTCTGGGCCCCGGGAAAAAA']
Maanijou 的回答很好。
另外,考虑使用迭代器的替代方案。
编辑:根据您的意见更新了代码
#!/usr/bin/env python
import sys
import os
myfasta = sys.argv[1]
fasta = open(myfasta, "r+")
file_contents = iter(fasta)
try:
print_flag = True
while True:
line = file_contents.next()
if line.startswith('>'):
if "CDS" in line:
print (line.strip())
print_flag = True
else:
print_flag = False
else:
if print_flag:
print (line.strip())
except StopIteration:
print ("Done")
fasta.close()
说明
file_contents = iter(fasta)
将可迭代文件 object 转换为一个迭代器,你可以简单地继续调用 next()
直到你 运行 没有东西可以读
为什么我不建议像其他一些答案那样调用 readlines
是因为有时 fasta 文件可能很大并且调用 readlines
会消耗大量内存。
如果一行满足您的搜索要求,您只需打印它和下一行,否则您只需阅读下一行而不做任何事情,
更新说明
- 由于文件模式,你得到了属性错误,我无法在本地重现它,但我认为用正确的模式打开文件应该可以解决这个问题
- 您现在说
CDS
的基因组序列可能不止 1 个更新了代码以打印文件中 1CDS
header 的所有基因组序列
我用修改过的 fasta 文件测试过它
>1_CDS
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGCG
>2_CDS
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>3_CDS
TTTGGGAATTAAACCCT
>4_CDS
TTTGGGAATTAAACCCT
>5_rRNA
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>6_tRNA
TTAAAAATTTCTGGGCCCCGGGAAAAAA
而这个输出
python fasta.py fasta.fasta
>1_CDS
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGGG
AAAAATTTCTGGGCCCCGGGCG
>2_CDS
TTAAAAATTTCTGGGCCCCGGGAAAAAA
>3_CDS
TTTGGGAATTAAACCCT
>4_CDS
TTTGGGAATTAAACCCT
Done