我有两组名字我希望找到两者之间最接近的匹配,如果没有"足够接近"找到匹配我想将名称与自己匹配。
我目前的方法是创建一个包含所有可能组合的数据框,并使用.apply或lists迭代并通过SequenceMatcher计算相似比(导入为sm)。
问题是我在两个列表中都有几千个名称,这导致了难以处理的运行时间。
理想情况下,我的匹配条件是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])
答案 0 :(得分:1)
您可能正在寻找的是Levenshtein距离算法。它计算将一个字符串转换为另一个字符串所需的最小编辑次数。
查看此库: https://github.com/ztane/python-Levenshtein/
Levenshtein库有一个名为StringMatcher.py的类,旨在帮助您解决这个问题。
此库还包含类似的功能:https://github.com/gfairchild/pyxDamerauLevenshtein