我有一个包含两列的20万行数据集:1 - 唯一的客户ID和地址组合以及2 - 收入。该表按收入排序,目标是通过与自身进行模糊匹配来清理第1列,以检查是否有足够接近的客户地址组合以及更高的收入,可用于替换收入较少的组合,这很可能是拼写差异造成的。
示例:
在上面的例子中,第三行与第一行非常相似,所以我希望它取第一行的值。
我有一个有效的python代码,但它太慢了:
import pandas as pd
import datetime
import time
import numpy as np
from pyxdameraulevenshtein import normalized_damerau_levenshtein_distance, normalized_damerau_levenshtein_distance_ndarray
data = pd.read_csv("CustomerMaster.csv", encoding="ISO-8859-1")
# Create lookup column from the dataframe itself:
lookup_data=data['UNIQUE_ID']
lookup_data=pd.Series.to_frame(lookup_data)
# Start iterating on row by row on lookup data to find the first closest fuzzy match and write that back into dataframe:
start = time.time()
for index,row in data.iterrows():
if index%5000==0:print(index, time.time()-start)
for index2, row2 in lookup_data.iterrows():
ratio_val=normalized_damerau_levenshtein_distance(row['UNIQUE_ID'],row2['UNIQUE_ID'])
if ratio_val<0.15:
data.set_value(index,'UPDATED_ID',row2['UNIQUE_ID'])
data.set_value(index,'Ratio_Val',ratio_val)
break
目前,这种模糊匹配的代码块运行时间太长 - 前15k行大约需要8小时,时间会按预期的速度呈指数级增长。关于如何更有效地编写此代码的任何建议?
答案 0 :(得分:1)
一个直接建议:由于匹配是对称的,因此您需要将每一行仅匹配尚未匹配的行。重写内部循环以跳过先前访问过的行。例如,添加:
if index2 <= index:
continue
仅此一项就可以将匹配速度提高2倍。
答案 1 :(得分:0)
我遇到了同样的问题,并通过levenshtein软件包(用于创建距离矩阵)和scikit的DBSCAN来解决,以将相似的字符串聚类,并将相同的值赋给聚类中的每个元素。
您可以在此处查看:https://github.com/ebravofm/e_utils(homog_lev())
>>> from e_utils.utils import clean_df
>>> from e_utils.utils import homog_lev
>>> series
0 Bad Bunny
1 bad buny
2 bag bunny
3 Ozuna
4 De La Ghetto
5 de la geto
6 Daddy Yankee
7 dade yankee
8 Nicky Jam
9 nicky jam
10 J Balvin
11 jbalvin
12 Maluma
13 maluma
14 Anuel AA
>>> series2 = clean_df(series)
>>> series2 = homog_lev(series2, eps=3)
>>> pd.concat([series, series2.str.title()], axis=1, keys=['*Original*', '*Fixed*'])
*Original* *Fixed*
0 Bad Bunny Bad Bunny
1 bad buny Bad Bunny
2 bag bunny Bad Bunny
3 Ozuna Ozuna
4 De La Ghetto De La Ghetto
5 de la geto De La Ghetto
6 Daddy Yankee Daddy Yankee
7 dade yankee Daddy Yankee
8 Nicky Jam Nicky Jam
9 nicky jam Nicky Jam
10 J Balvin J Balvin
11 jbalvin J Balvin
12 Maluma Maluma
13 maluma Maluma
14 Anuel AA Anuel Aa