是否有可能做模糊匹配与pythonpandas合并?

我有两个我想要基于列合并的DataFrames。 然而,由于不同的拼写,不同数量的空格,不存在变音符号,我希望能够合并,只要他们是相似的。

任何相似性algorithm都可以(soundex,Levenshtein,difflib)。

假设一个DataFrame有以下数据:

df1 = DataFrame([[1],[2],[3],[4],[5]], index=['one','two','three','four','five'], columns=['number']) number one 1 two 2 three 3 four 4 five 5 df2 = DataFrame([['a'],['b'],['c'],['d'],['e']], index=['one','too','three','fours','five'], columns=['letter']) letter one a too b three c fours d five e 

然后我想要得到的结果DataFrame

  number letter one 1 a two 2 b three 3 c four 4 d five 5 e 

与@locojaybuild议类似,您可以将difflibget_closest_matches应用于df2的索引,然后应用join

 In [23]: import difflib In [24]: difflib.get_close_matches Out[24]: <function difflib.get_close_matches> In [25]: df2.index = df2.index.map(lambda x: difflib.get_close_matches(x, df1.index)[0]) In [26]: df2 Out[26]: letter one a two b three c four d five e In [31]: df1.join(df2) Out[31]: number letter one 1 a two 2 b three 3 c four 4 d five 5 e 

如果这些是列,就可以用同样的方式应用到列,然后merge

 df1 = DataFrame([[1,'one'],[2,'two'],[3,'three'],[4,'four'],[5,'five']], columns=['number', 'name']) df2 = DataFrame([['a','one'],['b','too'],['c','three'],['d','fours'],['e','five']], columns=['letter', 'name']) df2['name'] = df2['name'].apply(lambda x: difflib.get_close_matches(x, df1['name'])[0]) df1.merge(df2) 

我会使用Jaro-Winkler,因为它是目前可用的性能最高和精确的近似string匹配algorithm之一[ Cohen,et al。 ],[ 温克勒 ]。

这就是我将如何与海蜇包中的Jaro-Winkler做到这一点:

 def get_closest_match(x, list_strings): best_match = None highest_jw = 0 for current_string in list_strings: current_score = jellyfish.jaro_winkler(x, current_string) if(current_score > highest_jw): highest_jw = current_score best_match = current_string return best_match df1 = pandas.DataFrame([[1],[2],[3],[4],[5]], index=['one','two','three','four','five'], columns=['number']) df2 = pandas.DataFrame([['a'],['b'],['c'],['d'],['e']], index=['one','too','three','fours','five'], columns=['letter']) df2.index = df2.index.map(lambda x: get_closest_match(x, df1.index)) df1.join(df2) 

输出:

  number letter one 1 a two 2 b three 3 c four 4 d five 5 e 

http://pandas.pydata.org/pandas-docs/dev/merging.html没有一个钩子函数来实现这一点。; 虽然会很好

我只做一个单独的步骤,并使用difflib getclosest_matches在两个数据框中的一个中创build一个新列,并在模糊匹配列上合并/连接

作为提醒,这基本上是有效的,除非找不到匹配,或者如果你在任何一列都有NaN。 而不是直接应用get_close_matches ,我发现应用下面的函数更容易。 NaN替代品的select将取决于您的数据集。

 def fuzzy_match(a, b): left = '1' if pd.isnull(a) else a right = b.fillna('2') out = difflib.get_close_matches(left, right) return out[0] if out else np.NaN