我正在尝试合并两个数据帧,不幸的是,唯一常见的列是Name列,它们没有100%相同的值。有没有一种方法可以根据概率匹配名称,比如说,如果两个值之间有80%或更多的匹配字符串,它们就会将它们匹配在一起。下面是我面对的一个例子;
df1= pd.DataFrame({"Name":["John", "Mary", "Sarah", "Jack"], "B":[1,2,3,4]})
df2= pd.DataFrame({"Name":["Jon", 'Mary", "Sara", "Jak", "lilly"], "C":["foo", "bar", "bar", "foo", "bar"]})
我是一个相当新的编码,我会感谢你的建议:(
如果您不需要太花哨的东西,那么内置的difflib.get_close_matches
可能就足够了:
from difflib import get_close_matches
def get_closest_match(name):
matches = get_close_matches(name, df1['Name']
if len(matches) > 0:
return matches[0]
else:
return None
df2['ClosestName'] = df2['Name'].apply(get_closest_match)
df1.merge(df2, left_on='Name', right_on='ClosestName')
结果:
Name_x B Name_y C ClosestName
John 1 Jon foo John
Mary 2 Mary bar Mary
Sarah 3 Sara bar Sarah
Jack 4 Jak foo Jack
根据@Scott Boston的建议,您可以使用fuzzywuzzy包。您需要创建一个新列,该列将包含df1中最相似的单词,然后您可以加入该列。
In [88]: df2['key'] = df2['Name'].apply(lambda x : [process.extract(x, df1['Name'], limit=1)][0][0][0])
In [89]: df2
Out[89]:
Name C key
0 Jon foo John
1 Mary bar Mary
2 Sara bar Sarah
3 Jak foo Jack
4 lilly bar Mary
In [90]: df2.merge(df1, left_on='key',right_on='Name')
Out[90]:
Name_x C key Name_y B
0 Jon foo John John 1
1 Mary bar Mary Mary 2
2 lilly bar Mary Mary 2
3 Sara bar Sarah Sarah 3
4 Jak foo Jack Jack 4
可能有两种解决方案。
如果您拥有列"Name"的所有有效名称(命名空间(,则第一个解决方案有效。然后,您可以迭代"名称"列中的值和:
- 使用命名空间中所有可能的值计算其距离(Levenstein距离应该有效(
- 选择距离最小(相似度最高(的并替换为2.5为了避免容易出错的更换,您可以设置距离的截止值
- 仅合并(外部联接(
对于没有所有有效名称的情况,可以使用其他数据帧的列"Name"中的所有值创建一个集,并将其视为命名空间。以下步骤相同。