【问题标题】:define a loop which returns different possibilities定义一个返回不同可能性的循环
【发布时间】:2016-11-30 11:16:25
【问题描述】:

你好,我对 python 很陌生。我有以下问题: 我想编写一个脚本,给定具有歧义的(dna)序列,写入所有可能的序列,(如果少于 100 个,如果有超过 100 个可能的序列,则会打印适当的错误消息) 对于 DNA 核苷酸歧义:http://www.bioinformatics.org/sms/iupac.html

例如:对于序列“AYGH”,脚本的输出将是“ACGA”, “ACGC”, “ACGT”, “ATGA”, “ATGC”“ATGT”。 A、C、G 和 T 是默认核苷酸。所有其他人都可以有不同的价值(见链接)。

所以我写了这个:

def possible_sequences (seq):
    poss_seq = ''
    for i in seq:
        if i=='A'or i=='C'or i=='G'or i=='T': 
            poss_seq += i 
        else: 
            if i== 'R':  
                poss_seq += 'A' # OR 'G', how should i implement this? 
            elif i == 'Y': 
                poss_seq += 'C' # OR T 
            elif i == 'S': 
                poss_seq += 'G' # OR C
            elif i == 'W': 
                poss_seq += 'A' # OR T 
            elif i == 'K': 
                poss_seq += 'G' # OR T
            elif i == 'M': 
                poss_seq += 'A' # OR C
            elif i == 'B': 
                poss_seq += 'C' # OR G OR T 
            elif i == 'D': 
                poss_seq += 'A' # OR G OR T 
            elif i == 'H': 
                poss_seq += 'A' # OR C OR T 
            elif i == 'V': 
                poss_seq += 'A' # OR C OR G 
            elif i == 'N': 
                poss_seq += 'A' # OR C OR G OR T 
            elif i == '-' or i == '.': 
                poss_seq += ' '
    return poss_seq

当我测试我的功能时: 可能的序列('ATRY-C') 我得到了:

'ATAC C'

但我应该得到:

'ATAC C'
'ATAT C' 
'ATGC C'
'ATGT C'

有人可以帮帮我吗?我知道当存在歧义时我必须重述并写第二个 poss_seq 但我不知道如何......

【问题讨论】:

  • 你只是循环一次。您需要循环遍历序列,然后每当遇到要更改的字母(即不是 A、C、G 或 T)时,循环遍历可能的替换。您必须嵌套这些循环才能获得所有排列。
  • 只是小费;你可以做 if i in 'RWMDHVN': poss_seq += 'A' 而不是写多个 if-elif 语句
  • 是的,这就是我想在最后一句话中说的。明白但不知道怎么实现?

标签: python function loops


【解决方案1】:

您可以使用itertools.product 来生成可能性:

from itertools import product

# List possible nucleotides for each possible item in sequence
MAP = {
    'A': 'A',
    'C': 'C',
    'G': 'G',
    'T': 'T',
    'R': 'AG',
    'Y': 'CT',
    'S': 'GC',
    'W': 'AT',
    'K': 'GT',
    'M': 'AC',
    'B': 'CGT',
    'D': 'AGT',
    'H': 'ACT',
    'V': 'ACG',
    'N': 'ACGT',
    '-': ' ',
    '.': ' '
}

def possible_sequences(seq):
    return (''.join(c) for c in product(*(MAP[c] for c in seq)))

print(list(possible_sequences('AYGH')))
print(list(possible_sequences('ATRY-C')))

输出:

['ACGA', 'ACGC', 'ACGT', 'ATGA', 'ATGC', 'ATGT']
['ATAC C', 'ATAT C', 'ATGC C', 'ATGT C']

在上面我们首先迭代给定序列中的项目并获得每个项目可能的核苷酸列表:

possibilities = [MAP[c] for c in 'ATRY-C']
print(possibilities)

# ['A', 'T', 'AG', 'CT', ' ', 'C']

然后将 iterable 解压缩为提供给 product 的参数,这将返回笛卡尔积:

products = list(product(*['A', 'T', 'AG', 'CT', ' ', 'C']))
print(products)

# [('A', 'T', 'A', 'C', ' ', 'C'), ('A', 'T', 'A', 'T', ' ', 'C'), 
#  ('A', 'T', 'G', 'C', ' ', 'C'), ('A', 'T', 'G', 'T', ' ', 'C')]

最后每一个产品都转成带有join的字符串:

print(list(''.join(p) for p in products))

# ['ATAC C', 'ATAT C', 'ATGC C', 'ATGT C']

请注意,possible_sequences 返回一个生成器,而不是一次构造所有可能的序列,因此您可以随时轻松停止迭代,而不必等待每个序列生成。

【讨论】:

  • 我还没有玩过 itertools,但它似乎非常强大。这似乎是最好的方法
  • 你打败了我。 :) 你想让我把我的完整版MAP 编辑成你的答案吗? FWIW,我可能只做MAP[c] 而不是MAP.get(c, ' '),因为如果我们得到错误的数据,我们可能想捕获关键错误。
  • @PM2Ring 感谢您的提议,但我可以做到。使用get 的唯一原因是第二个示例中包含-,但在结果中它丢失了。如果需要捕获错误,那么索引运算符是可行的。
  • @samb8s 请注意,niemmi 的 possible_sequences 函数是一个生成器,因此如果您不需要将所有可能的组合存储在一个列表中,您可以使用 for s in possible_sequences('AYGH'): 逐个迭代组合一。显然,如果输入序列很大并且有很多不在“ACGT”中的字母,那么您可以获得 lots 的组合。 :)
  • 好的。 FWIW,我把 '-': ' ', '.': ' ', 放在我的 MAP 版本中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-05
  • 2011-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多