[英]python how to efficiently group together terms
我有以下格式的数据:
<abc> <anything2> <anything3>.
<_901> <first> <something1>.
<_905> <second> <something2>.
<_910> <anything> <something3>.
<_901> <second> <something4>.
<_905> <first> <something6>.
<_901> <third> <something5>.
<_905> <third> <something7>.
现在,我想将与第一列和第二列的(第一,第二,第三)值相对应的所有信息分组在一起,以便以以下形式获得汇总信息:
<abc> <anything2> <anything3>.
<_901> <something1> <something4> <something5>.
<_905> <something6> <something2> <something7>.
<_910> <anything> <something3>.
我试图使用python字典来实现这一点。 但是由于我有2 Tera字节的文件。 我的过程内存不足,效率很低。 python中是否有更快的方法来实现这一点。 如果是,那么有人可以举例说明吗?
首先,您可以尝试使用unix工具sort
对数据进行sort
(它可以很好地处理非常大的文件)。 然后,具有相同的第一字段和第二字段的行将处于连续块中,以便您可以使用python脚本遍历它们并以您喜欢的格式输出。 下面给出了一个示例,用于您不希望第二列中没有第一,第二或第三数据的情况。
# merger.py
# this python script takes in a file with sorted lines and gives your output
import sys
prevtag = None
data = ['', '', '']
printed = True
for line in sys.stdin:
fields = line.strip().split()
if fields[0] != prevtag:
if not printed:
print prevtag, ' '.join(data)
printed = True
prevtag = fields[0]
data = ['', '', '']
if fields[1] == '<first>':
data[0] = fields[2]
printed = False
if fields[1] == '<second>':
data[1] = fields[2]
printed = False
if fields[1] == '<third>':
data[2] = fields[2]
printed = False
if not printed:
print prevtag, ' '.join(data)
现在,您可以将sort
的输出通过管道传递到此脚本中,以实现所需的功能。
sort <inputfile> | python merger.py
输入:
<abc> <anything2> <anything3>
<_901> <first> <something1>
<_905> <second> <something2>
<_910> <anything> <something3>
<_901> <second> <something4>
<_905> <first> <something6>
<_901> <third> <something5>
<_905> <third> <something7>
输出:
<_901> <something1> <something4> <something5>
<_905> <something6> <something2> <something7>
这可能会给您一些想法。 我使用了David Beazely关于“ 面向系统程序员的生成器技巧”讲座中的一些内容。 由于您的文件很大,因此我将<something>
值存储在单独的文件中。 您也许可以将它们附加到列表/字典中; 我不确定。 每次打开,添加和关闭文件对我来说似乎效率很低,但我想不出其他任何东西。
from __future__ import division, print_function
from StringIO import StringIO
import re
import os
import glob
#for generator details see see http://www.dabeaz.com/generators/
def gen_grep_groups(pat, lines):
patc = re.compile(pat)
for line in lines:
match = patc.search(line)
if match:
yield match.groups()
def logme(pairs, ext='.special_list'):
for name, thing in pairs:
#there must be a better way than opening and closing each time
f = open(name + ext,'a')
f.writelines(thing +'\n')
f.close()
data = StringIO("""<abc> <anything2> <anything3>.
<_901> <first> <something1>.
<_905> <second> <something2>.
<_910> <anything> <something3>.
<_901> <second> <something4>.
<_905> <first> <something6>.
<_901> <third> <something5>.
<_905> <third> <something7>.""")
#for a file use data = open(filename)
pat = r'<(.+?)>\s+<(?:first|second|third)>\s+<(.+?)>'
ext = ".special_list"
#patternc = re.compile(pattern)
for f in glob.glob('*'+ ext):
os.remove(f) #remove any existing files
pairs = gen_grep_groups(pat,data)
logme(pairs, ext)
for filename in glob.glob('*'+ ext):
#do what you want in here
name = os.path.splitext(filename)[0]
print(name)
f = open(filename,'r')
print(f.read())
f.close()
对于这么大的文件,可能需要多次读取。
首先,阅读各行,并将关键字段与数据所在的行号(或者可能更好:文件位置)一起存储:
pos = {}
filepos = file.tell()
for line in file:
sline = line.split()
pos.setdefault(sline[0], []).append(filepos)
filepos.file.tell() # for the next read
现在您有了一个字典,例如{'':[0],<_901>:[25,87],...}
现在您可以遍历字典并执行
for key, fileposes in pos.iteritems():
if len(fileposes) == 1:
file.seek(fileposes[0])
print file.readline()
else:
outlinedata = []
for filepos in fileposes:
file.seek(fileposes[0])
line = file.readline()
sline = line.split()
outlinedata.append(sline[2])
print key, " ".join(outlinedata)
(但是我不确定是否tell/seek
一方面tell/seek
,并且文件的逐行读取和缓冲不会互相干扰...)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.