pandas 数据框中的匹配(fuzzywuzzy)
Posted
技术标签:
【中文标题】pandas 数据框中的匹配(fuzzywuzzy)【英文标题】:Matching in pandas dataframe (fuzzywuzzy) 【发布时间】:2021-10-22 00:50:06 【问题描述】:我有一个数据框,其中一列包含公司名称(数据框大约有 50 列)。例如
Name
byname_tt
standing_re
mystandying_tz
mouse_x
mousepad_db
我正在尝试再创建一列,其中包含来自已检查名称的相似名称列表。为了比较我正在使用的名称,fuzzywuzzy。
def check_name(name):
check = df.apply(lambda row: ((fuzz.partial_ratio(row['Name'], name)) >= 50), axis=1)
return [df.Name[i] for i, x in enumerate(check) if x]
如果匹配高于阈值,我的预期输出应该类似于
Name Checked
byname_tt []
standing_re ['mystandying_tz']
mystandying_tz ['standing_re']
mouse_x ['mousepad_db']
mousepad_db ['mouse_x']
目前,我的输出是错误的:
Name Checked
byname_tt ['byname_tt']
standing_re ['standing_re']
mystandying_tz ['mystandying_tz']
mouse_x ['mouse_x']
mousepad_db ['mousepad_db']
对于名称中的每个名称,我应该检查与名称列中其他名称的相似性。 知道出了什么问题吗?
【问题讨论】:
这里检查的名称是什么?您是否将所有公司名称与所有其他公司名称进行核对? 【参考方案1】:如果你要匹配所有字符串对,你可以从生成所有这些你想要比较的字符串对开始,然后在出现两次相同的单词时删除:
>>> pairs = pd.merge(df['Name'], df['Name'].rename('Checked'), how='cross', suffixes=('', ''))
>>> pairs = pairs[pairs['Name'] != pairs['Checked']]
然后你可以使用你的 fuzz 库进行比较,我将使用 python 的 difflib 作为这个例子 - 它不一定更好,但它会避免安装另一个包,因为它大致相同。
>>> pairs['ratio'] = pairs.agg(lambda s: difflib.SequenceMatcher(None, s['Name'], s['Checked']).ratio(), axis='columns')
>>> pairs
Name Checked ratio
1 byname_tt standing_re 0.200000
2 byname_tt mystandying_tz 0.347826
3 byname_tt mouse_x 0.375000
4 byname_tt mousepad_db 0.100000
5 standing_re byname_tt 0.100000
7 standing_re mystandying_tz 0.720000
8 standing_re mouse_x 0.222222
9 standing_re mousepad_db 0.363636
10 mystandying_tz byname_tt 0.260870
11 mystandying_tz standing_re 0.720000
13 mystandying_tz mouse_x 0.285714
14 mystandying_tz mousepad_db 0.400000
15 mouse_x byname_tt 0.375000
16 mouse_x standing_re 0.222222
17 mouse_x mystandying_tz 0.285714
19 mouse_x mousepad_db 0.666667
20 mousepad_db byname_tt 0.300000
21 mousepad_db standing_re 0.181818
22 mousepad_db mystandying_tz 0.400000
23 mousepad_db mouse_x 0.666667
最后我们可以简单地过滤比率并使用简单的 groupby 生成列表:
>>> similar = pairs[pairs['ratio'] > .5].groupby('Name')['Checked'].agg(list)
>>> similar
Name
mouse_x [mousepad_db]
mousepad_db [mouse_x]
mystandying_tz [standing_re]
standing_re [mystandying_tz]
Name: Checked, dtype: object
>>> df.merge(similar.reindex(pairs['Name'].unique(), fill_value=[]), on='Name', how='outer')
Name Checked
0 byname_tt []
1 standing_re [mystandying_tz]
2 mystandying_tz [standing_re]
3 mouse_x [mousepad_db]
4 mousepad_db [mouse_x]
最后的reindex
是一个小解决方法,可以在没有匹配的行上获得[]
的填充,因为您不能将列表作为参数传递给fillna()
。
【讨论】:
感谢辛巴利。我收到此错误:ValueError:fill_value 必须是标量。你知道我该如何解决它或者我应该看什么来解决它吗? @LdM 我已经更新了,fillna 不接受列表作为参数。以上是关于pandas 数据框中的匹配(fuzzywuzzy)的主要内容,如果未能解决你的问题,请参考以下文章
将语料库中的名称部分匹配到 Pandas 数据框中另一列中的名称