有效地查找部分字符串匹配-->;使用Python从5 GB文件中的值列表开始的值
我有一个5GB的企业文件,我试图提取所有的企业,它们的企业类型代码(SNACODE)以对应于杂货店的SNACODE开头。例如,某些企业的SNACODEs可能是42443013、4451103、44419041、44512001、4452004,我希望所有企业的代码都以我的杂货店SNACODEs代码列表开始=[4451445244777245299451212]。在本例中,我将获得44511003、44512001和4452004的行 根据我在谷歌上搜索的内容,读取文件的最有效方式似乎是一次读取一行(如果不是SQL路由的话)。然后我使用for循环,检查SNACODE列是否以我的任何代码开头(这可能是个坏主意,但这是我开始工作的唯一方法) 我不知道文件中有多少行,但有84列。我的电脑运行了很长时间,我问一位朋友,他说完成这项任务只需要10-20分钟。我的朋友编辑了代码,但我想他误解了我的意图,因为他的结果没有返回任何结果 我现在正试图找到一种比重新工作9.5个小时,让笔记本电脑运行未知时间更有效的方法。我能找到的最接近的东西是,但它似乎不像我要找的 问题: 最好的方法是什么?这需要多长时间?有效地查找部分字符串匹配-->;使用Python从5 GB文件中的值列表开始的值,python,pandas,bigdata,string-matching,data-extraction,Python,Pandas,Bigdata,String Matching,Data Extraction,我有一个5GB的企业文件,我试图提取所有的企业,它们的企业类型代码(SNACODE)以对应于杂货店的SNACODE开头。例如,某些企业的SNACODEs可能是42443013、4451103、44419041、44512001、4452004,我希望所有企业的代码都以我的杂货店SNACODEs代码列表开始=[4451445244777245299451212]。在本例中,我将获得44511003、44512001和4452004的行 根据我在谷歌上搜索的内容,读取文件的最有效方式似乎是一次读取一
有没有办法从我停下来的地方开始?(我不知道我读取了多少行5gb文件,但我有最后保存的数据行——有没有一种快速/简单的方法可以在不必读取每一行的情况下找到与文件中唯一ID对应的行?) 这就是我尝试过的——在9.5小时内,它输出了一个72MB的杂货店文件(200k+行) 这是我朋友编辑的。我非常确定
x=df[df.SNACODE.isin(codes)]
只匹配完美匹配,因此不返回任何结果
codes = [4451,4452,447,772,45299,45291,45212]
matched = []
for df in pd.read_csv('infogroup_bus_2010.csv',sep=',', chunksize=1024*1024, dtype = str, low_memory=False):
x = df[df.SNACODE.isin(codes)]
if len(x):
matched.append(x)
print "Processed chunk and found {} matches".format(len(x))
output = pd.concat(matched, axis=0)
output.to_csv("grocery.csv", index = False)
谢谢 为了提高速度,您可以预先构建一个与所需行匹配的regexp,然后读取原始文件行(无csv解析)并使用regexp检查它们
codes = [4451,4452,447,772,45299,45291,45212]
col_number = 4 # Column number of SNACODE
expr = re.compile("[^,]*," * col_num +
"|".join(map(str, codes)) +
".*")
for L in open('infogroup_bus_2010.csv'):
if expr.match(L):
print L
请注意,这只是一个简单的草图,因为不考虑转义。。。如果SNACODE列不是第一列,并且前面的字段可能包含逗号,则需要更复杂的regexp,如:
...
'([^"][^,]*,|"([^"]|"")*",)' * col_num +
...
这忽略了双引号中的逗号您可能可以使pandas解决方案更快:
codes = [4451, 4452, 447, 772, 45299, 45291, 45212]
codes = [str(code) for code in codes]
sna = pd.read_csv('infogroup_bus_2010.csv', usecols=['SNACODE'],
chunksize=int(1e6), dtype={'SNACODE': str})
with open('grocery.csv', 'w') as fout:
for chunk in sna:
for code in chunk['SNACODE']:
for target_code in codes:
if code.startswith(target_code):
fout.write('{}\n'.format(code))
使用
usecols=['SNACODE']
仅读取所需的列。您可以使用chunksize=int(1e6)
调整块大小。根据您的RAM,您可能会使其更大。您应该创建一个测试文件,该文件只运行一两分钟,然后您可以测试算法,看看哪一个算法最有效。对于简单的字符串匹配,您可以通过从需求中删除熊猫来简化很多。如果这是一次性的,我认为从中间的某个地方继续下去是不值得的。请从头到尾重新运行。抱歉,我对您的最后一条评论感到困惑:“请注意,这只是一个简单的示意图,因为没有考虑转义……如果SNACODE列不是第一列,并且前面的字段可能包含逗号,则需要更复杂的regexp。”您能详细说明一下吗?@user3768258:此代码用于跳过SNACODE字段前面的字段的regexp是[^,]*,[^,]*,…
,即零个或多个非逗号后跟一个逗号的序列。但是,如果字段内容是例如“嘿,伙计”,则逗号会被引用,不应被视为字段分隔符。当然,可以编写一个可以跳过引号逗号的regexp,但更复杂的是,[^,]*
。一般来说,将L保存为一个新数据帧,然后将其作为一个大df写入末尾,还是将每一行都写入?谢谢Python缓冲是可以的。。。这种处理(读一行,写一行)通常相当快,所有耗时的工作都是用C语言完成的。对于5Gb的输入,我不会期望很长的计算时间(当然不是几个小时)。为了获得最大的速度,我会使用C++版本的代码> MMAP< /Cord>来访问文件内容…对于这种处理,我希望它的速度与复制5Gb文件的速度基本相同。如果需要对同一数据进行多个不同的搜索,那么建立索引可能是更好的方法。。。
codes = [4451, 4452, 447, 772, 45299, 45291, 45212]
codes = [str(code) for code in codes]
sna = pd.read_csv('infogroup_bus_2010.csv', usecols=['SNACODE'],
chunksize=int(1e6), dtype={'SNACODE': str})
with open('grocery.csv', 'w') as fout:
for chunk in sna:
for code in chunk['SNACODE']:
for target_code in codes:
if code.startswith(target_code):
fout.write('{}\n'.format(code))