找到两组名称之间最接近的近似匹配

时间:2017-01-16 02:18:53

标签: python performance list pandas sequencematcher

我有两组名字我希望找到两者之间最接近的匹配,如果没有"足够接近"找到匹配我想将名称与自己匹配。

我目前的方法是创建一个包含所有可能组合的数据框,并使用.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])

1 个答案:

答案 0 :(得分:1)

您可能正在寻找的是Levenshtein距离算法。它计算将一个字符串转换为另一个字符串所需的最小编辑次数。

查看此库: https://github.com/ztane/python-Levenshtein/

Levenshtein库有一个名为StringMatcher.py的类,旨在帮助您解决这个问题。

此库还包含类似的功能:https://github.com/gfairchild/pyxDamerauLevenshtein