正则表达式使用列表元素搜索在大文档中查找匹配项

时间:2012-02-18 22:12:56

标签: python regex list

这是我的第一个脚本,我正在尝试比较两个基因组文件,其中一个数据点比另一个更多。

文件内容如下所示:

rs3094315       1       742429  AA
rs12562034      1       758311  GG
rs3934834       1       995669  CC

每个字段之间都有标签。每个文件大约有500,000行。

为了便于比较它们,我想只保留两个文件所包含的数据点,并丢弃其中任何一个所特有的任何数据点。为此,我创建了一个独特的所有DNA位置列表,现在我试图搜索原始数据文件的每一行,并将所有不包含这些独特DNA位置的行打印到新文件中。

我的代码中的所有内容都已经完成,直到我尝试使用正则表达式搜索基因组文件来打印所有非独特的DNA位置。我可以让脚本打印LaurelSNP_left循环中for列表中的所有项目,但是当我尝试对每个项目使用re.match时,我收到以下错误消息:

Traceback (most recent call last):
  File "/Users/laurelhochstetler/scripts/identify_SNPs.py", line 57, in <module>
    if re.match(item,"(.*)", Line):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/re.py", line 137, in match
    return _compile(pattern, flags).match(string)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/re.py", line 242, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/sre_compile.py", line 500, in compile
    p = sre_parse.parse(p, flags)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/sre_parse.py", line 673, in parse
    p = _parse_sub(source, pattern, 0)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/sre_parse.py", line 308, in _parse_sub
    itemsappend(_parse(source, state))
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/sre_parse.py", line 401, in _parse
    if state.flags & SRE_FLAG_VERBOSE:
TypeError: unsupported operand type(s) for &: 'str' and 'int'

我的问题是双重的:

  1. 如何在正则表达式中使用我的列表?
  2. 有没有更好的方法来完成我在这里要做的事情?
  3. 这是我的代码:

    #!/usr/bin/env python
    import re #this imports regular expression module
    import collections
    
    MomGenome=open('/Users/laurelhochstetler/Documents/genetics fun/genome_Mary_Maloney_Full_20110514145353.txt', 'r')
    LaurelGenome=open('/Users/laurelhochstetler/Documents/genetics fun/genome_Laurel_Hochstetler_Full_20100411230740.txt', 'r')
    LineNumber = 0 
    momSNP = []
    LaurelSNP = []
    f = open("mom_edit.txt","w")
    for Line in MomGenome:
        if LineNumber > 0:
            Line=Line.strip('\n')
            ElementList=Line.split('\t')
    
            momSNP.append(ElementList[0])
    
            LineNumber = LineNumber + 1
    MomGenome.close()
    for Line in LaurelGenome:
        if LineNumber > 0:
            Line=Line.strip('\n')
            ElementList=Line.split('\t')
    
            LaurelSNP.append(ElementList[0])
    
            LineNumber = LineNumber + 1
    momSNP_multiset = collections.Counter(momSNP)            
    LaurelSNP_multiset = collections.Counter(LaurelSNP)
    overlap = list((momSNP_multiset and LaurelSNP_multiset).elements())
    momSNP_left = list((momSNP_multiset - LaurelSNP_multiset).elements())
    LaurelSNP_left = list((LaurelSNP_multiset - momSNP_multiset).elements())
    LaurelGenome=open('/Users/laurelhochstetler/Documents/genetics fun/genome_Laurel_Hochstetler_Full_20100411230740.txt', 'r')
    i = 0
    for Line in LaurelGenome:
        for item in LaurelSNP_left:
                if i < 1961:
                    if re.match(item, Line):
                        pass
    
                    else:
                        print Line
    
                i = i + 1
        LineNumber = LineNumber + 1
    

4 个答案:

答案 0 :(得分:2)

简短回答:我认为你不需要regexp来做你想做的事。

答案很长:让我们分析你的代码。

一开始就有:

LineNumber = 0 
MomGenome = open('20110514145353.txt', 'r')
for Line in MomGenome:
    if LineNumber > 0:
        Line = Line.strip('\n')
        ElementList = Line.split('\t')

        momSNP.append(ElementList[0])

        LineNumber = LineNumber + 1

MomGenome.close()

可以使用with语句对其进行改进,我猜您的行计数仅用于跳过某种标题,我将使用next()

with open('20110514145353.txt') as mom_genome:
    next(mom_genome)    # skipping the first line
    for line in mom_genome:
        elements = line.strip().split('\t')
        mom_SNP.append(elements[0])

如果你注意到我也试图避免使用CamelCase名称作为变量,这样你就会遵循一些风格指南。我还将.strip('\n')更改为.strip()检查官方str.strip(),看看是否仍然符合您的要求。
以上内容也可以在你的其他文件上完成。

读完文件之后就有了这一行:

overlap = list((momSNP_multiset and LaurelSNP_multiset).elements())

你确定这可以做你想要的吗? and不应该是&,例如:

overlap = list((momSNP_multiset & LaurelSNP_multiset).elements())

让我们看一下这个例子:

>>> from collections import Counter
>>> a = Counter(a=4, b=2, c=0, d=-2)
>>> b = Counter(a=2, b=0, c=0)
>>> a
Counter({'a': 4, 'b': 2, 'c': 0, 'd': -2})
>>> b
Counter({'a': 2, 'c': 0, 'b': 0})
>>> a and b    # This will return b
Counter({'a': 2, 'c': 0, 'b': 0})
>>> c & d    # this will return the common elements
Counter({'a': 2})

a and b它将返回b,因为bool(a)被评为True,请查看official doc

之后是比赛,这真的不太清楚。你这样做:

LaurelGenome = open('20100411230740.txt', 'r')
i = 0
for Line in LaurelGenome:
    for item in LaurelSNP_left:
        if i < 1961:
            if re.match(item, Line):
                pass
            else:
               print Line

        i = i + 1
    LineNumber = LineNumber + 1

正如我在开始时所说的那样,我认为你根本不需要正则表达式 而且我认为您正在尝试执行以下操作:

with open('20100411230740.txt') as laural_genome:
    for line in laureal_genome:
        i = 0
        for item in laurelSNP_left:
            if i > 1960:
                break

            if line.strip().split('\t')[0] == item:
                print line

            i += 1

我在这个答案中猜到了很多,所以请随时提供更多信息并告诉我猜错了:)

答案 1 :(得分:1)

re.match的第三个参数是选项(参见手册)。你用虚假的东西(行号)

来称呼它

答案 2 :(得分:0)

我是否遗漏了对此问题至关重要的内容?我觉得这个解决方案比现有的解决方案要少得多。对于两个不同的基因组文件,我有:

with file('zzz.txt') as f1:
    first = frozenset([i.strip() for i in f1 if i.strip()])

with file('yyy.txt') as f2:
    common = [i.strip().split('\t') for i in f2 if i.strip() in first]

genomes = {}
for i in common:
    genomes[i[0]] = i[1:]

这应该打印出所有重复项(两个文件共有的条目),同时不需要比第一个读取文件大小更多的空间。因此,您可以通过事先检查哪个是较小的文件(可能是文件大小)来加快速度,以最大限度地减少内存影响。

这里似乎没有必要使用正则表达式 - 如果不是这个解决方案,如果你不喜欢使用列表推导,那么frozensets也会有交集。

编辑:已更新为在Python dict中进行每次迭代。

答案 3 :(得分:0)

您希望打印文件2中的每一行,其ID不会出现在文件1中。在文件1中创建一组ID,并在循环浏览文件2时使用它们:

momSNP = set()
for line in MomGenome:
    snp, rest = line.split(None, 1) # Split into two pieces only
    momSNP.add(snp)

for line in MyGenome:
    snp, rest = line.split(None, 1)
    if snp in momSNP:
        print line

这只需要存储500k个SNP,因此记忆不应该太大。