从列中获取索引,然后使用它从大型文件的其他列中获取值

时间:2017-12-07 15:09:39

标签: python regex

我有一个非常大的文件,包含许多行和行。为了简化我的问题,我们假设有201列。第一列与AB:CD:EF:GH类似,其他列与1:2:3:4类似。正如所见,分隔符是相同的。所有列的模式应该是相同的。如果第一列有3个分隔符,则表示给定行中的所有其他分隔符有3个分隔符。

例如,我想知道该行第一列中EF的索引,并使用该索引从所有列中获取3EF的索引在各行各不相同。

我使用了两种拆分方法。但是,由于我的文件很大,它会为我的代码带来很大的瓶颈。顺便说一下,有超过一千万行。

with open("amkhepinizin.txt", "r") as theFile:
    for line in theFile:
        ind = line[0].split(":").index("EF")
        theList = []
        for j in range(1,202):
            theList.append(line[j].split(":")[ind])
        foo(theList)  # some processes 

它有效,但有点慢。我发现每行调用大约200次的拆分方法会导致代码运行缓慢。我认为我可以通过使用正则表达式来解决这个问题,我一开始并不知道。我试图找出如何使用正则表达式,但我不能。

这是我文件的一个小例子。

EF:AD:DP:GQ:PL    0/0:95,0:96:99:0,214,2836    0/1:103,0:103:99:0,229,3036
AD:EF:DP:GQ:PL    0/1:16,7:25:99:242:5,1,6     0/0:32,0:33:93:0,93,1102 
DP:GQ:EF          99:533,0,422:1               99:310,0,1129:6
::EF:DP:          ::::                         0::0::

基本上,我想从第一行获得0/00/1;然后来自第二行的16,732,0以及来自第三行的16。来自第四行的""0

你能帮我解决一下如何在我的代码中实现正则表达式。

如果您认为正则表达式没有加强我的代码,我会很感激其他建议。

1 个答案:

答案 0 :(得分:0)

它可能会加快您的代码使用某些生成器:

import re

data = """
EF:AD:DP:GQ:PL    0/0:95,0:96:99:0,214,2836    0/1:103,0:103:99:0,229,3036
AD:EF:DP:GQ:PL    0/1:16,7:25:99:242:5,1,6     0/0:32,0:33:93:0,93,1102 
DP:GQ:EF          26:99:533,0,422:1            39:99:310,0,1129:6
::EF:DP:          ::::                         0::0::
"""

rx_needle = 'EF'

rx_lines = re.compile(r'.+')
rx_split = re.compile(r'\s{2,}')

def item_getter(line, needle):
    parts = rx_split.split(line)

    try:
        ind = parts[0].split(':').index(needle)
        values = (p[ind] for part in parts[1:] for p in [part.split(':')])
        return values
    except ValueError:
        return None

for line in rx_lines.finditer(data):
    values = item_getter(line.group(0), rx_needle)
    # do whatever you want to do with values here
    print(list(values))

这里的想法是使用生成器来查找re.finditer()的下一行,并使用另一个生成器从该行获取特定值(给定针被找到)。
优点是你可以在将来的某个特定时间停止(让我们说在1000行之后),并且只使用少量(呃)的内存。

<小时/> 速度示例:

def t():
    for line in rx_lines.finditer(data):
        values = item_getter(line.group(0), rx_needle)

import timeit
s = timeit.timeit(t, number=10**5)
print(s)
# 3.28 s

因此,要对400k行运行该函数,大约需要3秒钟。