【问题标题】:How to generate all possible patterns from a set of letters?如何从一组字母中生成所有可能的模式?
【发布时间】:2019-06-26 11:23:20
【问题描述】:

如何通过使用 k 参数来简化此函数中的 for 循环?

def PatternGenerate(k):
    base = ['A','C','G','T']
    pattern = []
    for x in base:
        for y in base:
            for z in base:
                result = str(x) + str(y) + str(z)
                pattern.append(result)
    return pattern

我得到了我想要的结果,但没有得到函数:

['AAA'、'AAC'、'AAG'、'AAT'、'ACA'、'ACC'、'ACG'、'ACT'、'AGA'、'AGC'、'AGG'、'AGT ','ATA','ATC','ATG','ATT','CAA','CAC','CAG','CAT','CCA','CCC','CCG','CCT', 'CGA'、'CGC'、'CGG'、'CGT'、'CTA'、'CTC'、'CTG'、'CTT'、'GAA'、'GAC'、'GAG'、'GAT'、'GCA ','GCC','GCG','GCT','GGA','GGC','GGG','GGT','GTA','GTC','GTG','GTT','TAA', 'TAC'、'TAG'、'TAT'、'TCA'、'TCC'、'TCG'、'TCT'、'TGA'、'TGC'、'TGG'、'TGT'、'TTA'、'TTC ', 'TTG', 'TTT']

【问题讨论】:

  • How to get all possible combinations of a list’s elements? 可能重复,例如 for combo in itertools.combinations('AAACCCGGGTTT',3): print combo
  • @tk421,你的命令的输出是不同的:例如,它产生了六次'GTT'
  • @AndriyMakukha,是的,您需要将其过滤为一组或类似的,以删除重复项。

标签: python bioinformatics


【解决方案1】:

如果你使用递归形式会容易得多。

def PatternGenerate(k):
    base = ['A','C','G','T']
    pattern = []
    if k == 1:
      return base
    else:
      for p in PatternGenerate(k-1):
        for b in base:
          pattern.append(p+b)

      return pattern

解释 这个想法是: 如果 k == 1,简单返回基数 如果 k > 1,找到 PatternGenerate(k-1) 并将其附加到 base。

【讨论】:

  • 与我的方法非常相似,但它会一次生成整个数组,这可能不是最佳的。生成器函数(使用yield)通常是首选,可以带来更高的性能。
【解决方案2】:

一种方法是使用递归。这是执行此操作的生成器函数示例:

def genAll(depth, base = ['A','C','G','T']):
    if depth <= 0:
        yield ''
    else:
        for char in base:
            for tail in genAll(depth - 1, base):
                yield char + tail

for comb in genAll(2):
    print(comb)

输出:

AA
AC
AG
AT
CA
CC
CG
CT
GA
GC
GG
GT
TA
TC
TG
TT

【讨论】:

    【解决方案3】:

    使用 itertools 的 Lazier 版本

    import itertools
    k = 2
    result = ["".join(t) for t in itertools.combinations_with_replacement(['A','C','G','T'], k)]
    print(result)
    

    combinations_with_replacement 内部的实现与@Andriy 非常相似。

    【讨论】:

    • 输出与预期不同。 combinations_with_replacement 显然将结果视为无序集(即使它返回元素的元组)。
    【解决方案4】:

    这是一种使用来自itertoolsrepeatproduct 的方法:

    from itertools import product, repeat
    
    # This one returns a list, like your version:
    def list_all_kmers(k):
        return ["".join(nucls) for nucls in product(*repeat("ACGT", k))]
    
    # This one generates k-mers one by one:
    def generate_all_kmers(k):
        # It seems "return" also works
        # I'm not sure it makes a difference here
        # but see https://stackoverflow.com/a/45620965/1878788
        yield from ("".join(nucls) for nucls in product(*repeat("ACGT", k)))
    
    for kmer in generate_all_kmers(3):
        print(kmer)
    

    结果:

    AAA
    AAC
    AAG
    AAT
    ACA
    ACC
    ACG
    ACT
    AGA
    AGC
    AGG
    AGT
    ATA
    ATC
    ATG
    ATT
    CAA
    CAC
    CAG
    CAT
    CCA
    CCC
    CCG
    CCT
    CGA
    CGC
    CGG
    CGT
    CTA
    CTC
    CTG
    CTT
    GAA
    GAC
    GAG
    GAT
    GCA
    GCC
    GCG
    GCT
    GGA
    GGC
    GGG
    GGT
    GTA
    GTC
    GTG
    GTT
    TAA
    TAC
    TAG
    TAT
    TCA
    TCC
    TCG
    TCT
    TGA
    TGC
    TGG
    TGT
    TTA
    TTC
    TTG
    TTT
    

    一些解释:

    repeat("ACGT", k) 生成 k 次 "ACGT"。从中制作列表时可以将其可视化:

    list(repeat("ACGT", 3))
    

    结果:

    ['ACGT', 'ACGT', 'ACGT']
    

    product(l1, l2, l3) 生成所有元组,其中第一个元素来自l1,第二个来自l2,第三个来自l3,其中l1l2l3 是“可迭代”,例如列表或字符串。这适用于任何数字或可迭代对象:

    零:

    list(product())
    

    结果:

    [()]
    

    一个:

    list(product("ACGT"))
    

    结果:

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

    两个:

    list(product("ACGT", "ACGT"))
    

    结果:

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

    等等

    但是,如果我们想使用repeat 的结果,我们必须使用* 来表示生成的元素必须作为单独的参数。在函数调用中f(*[l1, l2, l3]) 就像在做f(l1, l2, l3)。如果你使用生成器而不是列表,它也可以工作,所以我们不需要做list(repeat(...))(我们只是为了可视化目的在上面做了)。

    然后我们想用元组中的元素制作字符串。这要归功于空字符串的join 方法,我们在“列表理解”([] 之间)或“生成器表达式”(() 之间)中使用。

    列表推导式创建完整列表,而生成器表达式“按需”生成元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-07
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      相关资源
      最近更新 更多