多处理模糊模糊字符串搜索 - python

时间:2017-06-21 03:23:25

标签: python python-2.7 python-multiprocessing dask fuzzywuzzy

我正在尝试进行字符串匹配,并在python中使用模糊wuzzy引入匹配ID。我的数据集非常庞大,数据集1 = 180万条记录,数据集2 = 160万条记录。

到目前为止我尝试了什么,

首先我尝试在python中使用record linkage包,遗憾的是它在构建multi index时内存不足,所以我移植到具有良好机器功能的AWS并成功构建它,但是当我试图对它进行比较,它会永远运行,我同意它的比较数量。

然后,我尝试与fuzzy wuzzy进行字符串匹配,并使用dask包并行处理该进程。并在样本数据上执行它。它工作正常,但我知道这个过程仍然需要时间,因为搜索空间很宽。我正在寻找一种方法来为这段代码添加阻塞或索引。

test = pd.DataFrame({'Address1':['123 Cheese Way','234 Cookie Place','345 Pizza Drive','456 Pretzel Junction'],'city':['X','U','X','U']}) 
test2 = pd.DataFrame({'Address1':['123 chese wy','234 kookie Pl','345 Pizzza DR','456 Pretzel Junktion'],'city':['X','U','Z','Y'] , 'ID' : ['1','3','4','8']}) 

在这里,我想在test.Address1中查找test2.Address1并带来ID

def fuzzy_score(str1, str2):
    return fuzz.token_set_ratio(str1, str2)

def helper(orig_string, slave_df):
    slave_df['score'] = slave_df.Address1.apply(lambda x: fuzzy_score(x,orig_string))
    #return my_value corresponding to the highest score
    return slave_df.ix[slave_df.score.idxmax(),'ID']

dmaster = dd.from_pandas(test, npartitions=24)
dmaster = dmaster.assign(ID_there=dmaster.Address1.apply(lambda x: helper(x, test2)))
dmaster.compute(get=dask.multiprocessing.get)

这很好用,但我不确定如何通过限制同一城市的搜索空间来对其进行索引。

可以说,我正在基于原始字符串的城市创建城市字段和子集的索引,并将该城市传递给辅助函数,

# sort the dataframe
test2.sort_values(by=['city'], inplace=True)
# set the index to be this and don't drop
test2.set_index(keys=['city'], drop=False,inplace=True)

我不知道该怎么办?请指教。提前致谢。

2 个答案:

答案 0 :(得分:1)

我更喜欢使用fuzzywuzzy.process.extractOne。这将字符串与可迭代的字符串进行比较。

def extract_one(col, other):
    # need this for dask later
    other = other.compute() if hasattr(other, 'compute') else other
    return pd.DataFrame([process.extractOne(x, other) for x in col],
                        columns=['Address1', 'score', 'idx'],
                        index=col.index)

extract_one(test.Address1, test2.Address1)

               Address1  score  idx
0          123 chese wy     92    0
1         234 kookie Pl     83    1
2         345 Pizzza DR     86    2
3  456 Pretzel Junktion     95    3

idx是传递给other的{​​{1}}与最近匹配的索引。我建议有一个有意义的索引,以便以后更容易地加入结果。

关于第二个问题,关于过滤到城市,我会使用groupby并应用

extract_one

与dask的唯一区别是需要为apply:

指定gr1 = test.groupby('city') gr2 = test2.groupby("city") gr1.apply(lambda x: extract_one(x.Address1, gr2.get_group(x.name).Address1)) Address1 score idx 0 123 chese wy 92 0 1 234 kookie Pl 83 1 2 345 Pizzza DR 86 2 3 456 Pretzel Junktion 95 3
meta

这是一个笔记本:https://gist.github.com/a932b3591346b898d6816a5efc2bc5ad

我很想知道表演是怎样的。我假设在模糊wuzzy中完成的实际字符串比较将占用大部分时间,但我很想知道在pandas和dask中花费了多少开销。确保你有计算Levenshtein距离的C扩展。

答案 1 :(得分:0)

我一次遇到相同的问题。整个过程将花费很长时间,即使您将使用多重处理,也并不是真的很快。导致速度降低的主要问题是模糊匹配,因为处理非常繁琐且需要大量时间。

在我看来,更有效的选择是使用嵌入又一袋的单词并在其上应用ML方法。您将使用数值向量的事实使整个过程更快!