Создание флага с использованием нечеткого сопоставления между двумя наборами данных в Python
У меня есть два набора данных df1 и df2, оба имеют следующие столбцы:
|city |state |address_id |address |postal_code
|A |X |10 |flat 123,abc lane |400000
Я хочу создать двоичный флаг для каждого address_id в df1 в зависимости от того, присутствует ли аналогичный адрес в df2. Мои оригинальные наборы данных довольно большие (df1= 5 тыс. Строк, df2= 200 тыс. Строк). Я опробовал следующий набор кодов на небольших выборках данных:
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 может использоваться как условие при нечетком сопоставлении, чтобы уменьшить количество итераций. Также, возможно, я могу прекратить итерации, как только мы достигнем a 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'
Только начал с питона, так что вроде застрял здесь. Пожалуйста помоги!
1 ответ
Я попробовал некоторые нечеткие сравнения для двух DF, и, насколько мне показалось, нет быстрого способа сделать это. Тот факт, что вы используете 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)