在 python 中的两个数据集之间使用 fuzzywuzzy 匹配创建标志
Creating flag using fuzzywuzzy matching between two datasets in python
我有两个数据集 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,所以有点卡在这里。请帮忙!
我在 2 个 DF 上尝试了一些 fuzzywuzzy 比较,就我的研究而言,没有快速的方法可以做到这一点。事实上,您使用 4 fuzz
方法也会减慢您的脚本。一种方法是使用“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)
我有两个数据集 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,所以有点卡在这里。请帮忙!
我在 2 个 DF 上尝试了一些 fuzzywuzzy 比较,就我的研究而言,没有快速的方法可以做到这一点。事实上,您使用 4 fuzz
方法也会减慢您的脚本。一种方法是使用“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)