DNA搜索序列正则表达式中的多个不匹配

时间:2011-12-14 17:51:33

标签: python regex biopython dna-sequence

我写了这个野蛮的脚本来创建一串字符的排列,这些字符在字符串中所有可能的位置组合中包含n(最多n = 4)$。我最终将.replace('$','(\\w)')用于dna搜索序列中的不匹配。由于我编写脚本的方式,一些排列少于请求的$的数量。然后我编写了一个脚本来删除它们,但它似乎没有效果,每次运行删除脚本时,它都会删除更多不需要的排列。在下面粘贴的代码中,您将看到我使用4个不匹配的简单序列测试函数。然后我运行一系列删除脚本,计算每次删除多少表达式...根据我的经验,删除所有表达式少于4张外卡的$表达式大约需要8次。我有几个问题:

  1. 是否有内置函数用于'n'不匹配的搜索?也许甚至在biopython中?到目前为止,我已经看过Paul_McGuire_regex函数:
    Search for string allowing for one mismatch in any location of the string
    这似乎只会产生1个不匹配。我必须承认,我并不完全理解该页面上剩余功能中的所有代码,因为我是一个非常新的编码器。

  2. 因为我认为这对我来说是一个很好的练习,是否有更好的方法来编写整个脚本?...我可以根据需要多次迭代Paul_McGuire_regex函数吗?

  3. 最令我困惑的是,为什么删除脚本第一次不会100%工作?

  4. 感谢您提供的任何帮助!

    def Mismatch(Search,n):
        List = []
        SearchL = list(Search)
        if n > 4:
            return("Error: Maximum of 4 mismatches")
        for i in range(0,len(Search)):
            if n == 1:
                SearchL_i = list(Search)
                SearchL_i[i] = '$'
                List.append(''.join(SearchL_i))
            if n > 1:
                for j in range (0,len(Search)):
                    if n == 2:
                        SearchL_j = list(Search)
                        SearchL_j[i] = '$'
                        SearchL_j[j] = '$'
                        List.append(''.join(SearchL_j))
                    if n > 2:
                        for k in range(0,len(Search)):
                            if n == 3:
                                SearchL_k = list(Search)
                                SearchL_k[i] = '$'
                                SearchL_k[j] = '$'
                                SearchL_k[k] = '$'
                                List.append(''.join(SearchL_k))
                            if n > 3:
                                for l in range(0,len(Search)):
                                    if n ==4:
                                        SearchL_l = list(Search)
                                        SearchL_l[i] = '$'
                                        SearchL_l[j] = '$'
                                        SearchL_l[k] = '$'
                                        SearchL_l[l] = '$'
                                        List.append(''.join(SearchL_l))
        counter=0
        for el in List:
            if el.count('$') < n:
                counter+=1
                List.remove(el)
        return(List) 
    
    List_RE = Mismatch('abcde',4)
    
    counter = 0
    for el in List_RE:
        if el.count('$') < 4:
            List_RE.remove(el)
            counter+=1
    
    print("Filter2="+str(counter))
    

1 个答案:

答案 0 :(得分:3)

我们可以通过回答问题1来解决问题2和问题3,但是理解问题3很重要,所以我先做,然后展示如何完全避免它:

问题3

关于问题3,这是因为当您在python中循环遍历列表并在循环中对其进行更改时,循环的列表会发生变化。

来自python docs on control flow (for statement section)

  

不安全修改循环中迭代的序列   (这只能发生在可变序列类型中,例如列表)。

说出您的列表为[a,b,c,d],然后使用for el in List循环显示该列表。 说el目前是a,而你List.remove(el)

现在,您的列表为[b,c,d]。但是,迭代器指向列表中的第二个元素(因为它是第一个完成的),现在是c。 从本质上讲,您已跳过b。所以问题是你正在修改你正在迭代的列表。

有几种方法可以解决这个问题:如果你的List复制成本不高,你可以复制一份。所以迭代List[:],但要从List中删除。

但是假设一直复制List是很昂贵的。 然后你做的是迭代向后。请注意下面的reversed

for el in reversed(List):
    if el.count('$') < n:
        counter+=1
        List.remove(el)
return(List) 

在上面的示例中,假设我们在List上向后迭代。 迭代器从d开始,然后转到c。 假设我们删除c,以便List=[a,b,d]。 由于迭代器向向后,它现在指向元素b,所以我们没有跳过任何东西。

基本上,这可以避免修改你尚未迭代的列表中的位。

问题1&amp; 2

如果我正确理解您的问题,您基本上想要从n个位置中选择m,其中m是字符串的长度(abcde),并且在这些n个职位中加上'$'。

在这种情况下,您可以使用itertools模块来执行此操作。

import itertools
def Mismatch(Search,n):
    SearchL = list(Search)
    List     = [] # hold output
    # print list of indices to replace with '$'
    idxs = itertools.combinations(range(len(SearchL)),n)        
    # for each combination `idx` in idxs, replace str[idx] with '$':
    for idx in idxs:
        str = SearchL[:] # make a copy
        for i in idx:
            str[i]='$'
        List.append( ''.join(str) ) # convert back to string
    return List

让我们来看看它是如何工作的:

  1. Search字符串转换为列表,以便迭代,创建空List以保存结果。
  2. idxs = itertools.combinations(range(len(SearchL)),n)说“在集合[0,1,2,3,...,length-of-search-string -1]中查找长度为n的所有子集。 试试

    idxs = itertools.combinations(range(5),4)
    for idx in idxs: 
        print idx
    

    看看我的意思。

  3. idxs的每个元素都是从0到n的{​​{1}}索引元组(例如len(SearchL)-1。将(0,1,2,4)的第i个字符替换为元组中每个SearchL的'$'。
  4. 将结果转换回字符串并将其添加到i
  5. 举个例子:

    List