我有两个数据集df1和df2,它们都有以下列:
|city |state |address_id |address |postal_code
|A |X |10 |flat 123,abc lane |400000
我想根据df2中是否存在类似的地址,为df1中的每个address_id创建一个二进制标志。我的原始数据集非常大(df1 = 5k行,df2 = 200K行)。我在小数据样本上尝试了以下代码:
for i in df1.index:
v=[]
for j in df2.index:
vi = df1.get_value(i, 'address')
vj = df2.get_value(j, 'address')
v.append(max(fuzz.ratio(vi, vj),
fuzz.partial_ratio(vi, vj),
fuzz.token_sort_ratio(vi, vj),
fuzz.token_set_ratio(vi, vj)))
vmax=max(v)
if vmax>=80:
df1.loc[i,'flag']='Y'
else:
df1.loc[i,'flag']='N'
但是这不会对更大的数据集起作用。有没有办法优化这个? postal_code可以用作模糊匹配的条件,以减少迭代次数。此外,也许我可以在达到v = 80时立即停止迭代。
for i in df1.index:
v=1
while v<=80:
for j in df2.index:
vi = df1.get_value(i, 'address')
vj = df2.get_value(j, 'address')
v= max(fuzz.ratio(vi, vj),
fuzz.partial_ratio(vi, vj),
fuzz.token_sort_ratio(vi, vj),
fuzz.token_set_ratio(vi, vj))
if v>=80:
df1.loc[i,'flag']='Y'
else:
df1.loc[i,'flag']='N'
刚开始使用python,所以有点卡在这里。请帮忙!
答案 0 :(得分:1)
我在2个DF上尝试了一些模糊的模糊比较,就我的研究而言,没有快速的方法可以做到。您使用4 fuzz
方法的事实也会减慢您的脚本速度。一种方法是使用&#39; process.extractOne()`并创建一个函数:
from fuzzywuzzy import process
def fw_process(row_df1):
# Select the addresses from df2 with same postal_code
df2_select_add = df2['address'][df2['postal_code'] == row_df1['postal_code']]
ad_1 = row_df1['address']
# Find the best match for ad_1 in df2_select_add and get the ratio with [1]
# for the name of df2_select_add , use [0]
if process.extractOne(ad_1, df2_select_add)[1] >= 80:
return 'Y'
else:
return 'N'
然后在df1
中创建列标志,您可以:
df1['flag'] = df1.apply(fw_process , axis=1)
注意:名称df2
不是作为函数的参数调用的,它不是更清洁的方式,但如果它在您的代码中使用此名称定义之前它的作用。
如果你想保留4个fuzz
方法,那么你可以创建相同想法的函数:
from fuzzywuzzy import fuzz
def fw_fuzz ( row_df1):
# Select the addresses from df2 with same postal_code
df2_select_add = df2['address'][df2['postal_code'] == row_df1['postal_code']]
ad_1 = row_df1['address']
# Get the max of the max of the 4 fuzz comparison between ad_1 and df2_select_add
if max (df2_select_add.apply(lambda x: max(fuzz.ratio(ad_1, x), fuzz.partial_ratio(ad_1, x),
fuzz.token_sort_ratio(ad_1, x),fuzz.token_set_ratio(ad_1, x)))) >= 80:
return 'Y'
else:
return 'N'
然后:
df1['flag'] = df1.apply(fw_fuzz, axis=1)