Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有效地查找部分字符串匹配-->;使用Python从5 GB文件中的值列表开始的值_Python_Pandas_Bigdata_String Matching_Data Extraction - Fatal编程技术网

有效地查找部分字符串匹配-->;使用Python从5 GB文件中的值列表开始的值

有效地查找部分字符串匹配-->;使用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的企业文件,我试图提取所有的企业,它们的企业类型代码(SNACODE)以对应于杂货店的SNACODE开头。例如,某些企业的SNACODEs可能是42443013、4451103、44419041、44512001、4452004,我希望所有企业的代码都以我的杂货店SNACODEs代码列表开始=[4451445244777245299451212]。在本例中,我将获得44511003、44512001和4452004的行

根据我在谷歌上搜索的内容,读取文件的最有效方式似乎是一次读取一行(如果不是SQL路由的话)。然后我使用for循环,检查SNACODE列是否以我的任何代码开头(这可能是个坏主意,但这是我开始工作的唯一方法)

我不知道文件中有多少行,但有84列。我的电脑运行了很长时间,我问一位朋友,他说完成这项任务只需要10-20分钟。我的朋友编辑了代码,但我想他误解了我的意图,因为他的结果没有返回任何结果

我现在正试图找到一种比重新工作9.5个小时,让笔记本电脑运行未知时间更有效的方法。我能找到的最接近的东西是,但它似乎不像我要找的

问题: 最好的方法是什么?这需要多长时间?
有没有办法从我停下来的地方开始?(我不知道我读取了多少行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))