У меня есть два набора имен, которые я хотел бы найти, самое близкое совпадение между ними, если не найдено совпадения «близко достаточно». Я хотел бы совместить имя с самим собой ,Поиск ближайшего приближенного совпадения между двумя наборами названий
Мой текущий подход заключается в создании кадра данных со всеми возможными комбинациями и использовании .apply или списков для перебора и вычисления отношения подобия через SequenceMatcher (импортируется как sm).
Проблема: у меня есть несколько тысяч имен в обоих списках, что приводит к неразрешимым временам выполнения.
Мои сопоставимые критерии в идеальном случае были бы отношением см>> 0,85 с первым именем, которое было бы найдено во втором имени как целое слово. Если эти критерии не выполняются, имя должно соответствовать самому себе.
Последний шаг, который я хотел бы реализовать, - это заменить исходную серию на эти согласованные имена.
Вот код для моего нынешнего подхода, пожалуйста, дайте мне знать, если это неясно, как я могу помочь уточнить:
stop_words = [
'pharmaceuticals',
'pharmaceutical',
'pharma',
'therapeutic',
'biopharma',
'therapeutics',
'international',
'biotechnology',
'vaccines',
'\&',
'&',
'co.',
'co',
'biotherapeutics',
'biotherapeutic',
'life science',
'life sciences',
'laboratories',
'biologics',
]
temp_db_companies = db['Company']
def approximate_match(s1, s2):
return str(sm(None, str(s1).lower().strip(), str(s2).lower().strip()).ratio()) + '|' + str(s2).strip()
def replace_val_w_best_match(df, col_initial, series_final, stop_words):
init_names = df[col_initial].str.lower().str.split(" ", expand=True).replace(stop_words, "").fillna('')
init_names = pd.Series(['' for n in range(len(init_names))]).str.cat([init_names[col] for col in init_names.columns], sep= " ").str.replace(' ', ' ').reset_index()
matching_df = pd.DataFrame(columns = list(init_names.columns) + list(series_final), data = init_names)
matching_df = pd.melt(matching_df,
id_vars = ['index', 0],
value_vars = list(series_final),
var_name = 'Comparators',
value_name = 'Best match')
# matching = matching_df.apply(lambda row: approximate_match(row[0], row['Comparators']), axis = 1)
l = [(matching_df[0]), list(matching_df['Comparators'])]
ratio = [sm(None, name1, name2) for name1 in l[0] for name2 in l[1]]
match = [name2 for name1 in l[0] for name2 in l[1]]
print(ratio[:5])
print(match[:5])
это более эффективен, чем последовательность согласовань? Моя проблема - это больше времени выполнения и способности сопоставлять приблизительные строки. – wingsoficarus116
Трудно сказать, не видя таймингов вашей существующей реализации, но если производительность является самой важной вещью, я бы рекомендовал сравнить вторую реализацию. Это написано в Китоне, поэтому оно должно быть очень быстрым. Тесты на библиотеке pyxDamerauLevenshtein показывают, что около 500 тыс. Сравнений за 2 минуты –
Похоже, что это на порядок быстрее, но мне нужно сначала установить MS Visual C++? Регулярная команда install install не работает. Извините, если это мирский вопрос, но я бы хотел выполнить ваши рекомендации. – wingsoficarus116