我有一个案例,我需要将给定字符串中的名称与名称数据库相匹配。下面我给出了一个非常简单的例子,说明我遇到的问题,我不清楚为什么一个案例对另一个案例有效?如果我没记错的话,extractOne() 的 Python 默认算法是 Levenshtein 距离算法。是不是因为 Clemens 的名字提供了前两个首字母,而 Gonzalez 的案例中只有一个?
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
s = ['Gonzalez, E. walked down the street.', 'Gonzalez, R. went to the market.', 'Clemens, Ko. reach the intersection; Clemens, Ka. did not.']
names = []
for i in s:
name = [] #clear name
for k in i.split():
if k[0].isupper(): name.append(k)
else: break
names.append(' '.join(name))
if ';' in i:
for each in i.split(';')[1:]:
name = [] #clear name
for k in each.split():
if k[0].isupper(): name.append(k)
else: break
names.append(' '.join(name))
print(names)
choices = ['Kody Clemens','Kacy Clemens','Gonzalez Ryan', 'Gonzalez Eddy']
for i in names:
s = process.extractOne(i, choices)
print(s, i)
Run Code Online (Sandbox Code Playgroud)
输出:
['Gonzalez, E.', 'Gonzalez, R.', 'Clemens, Ko.', 'Clemens, Ka.']
('Gonzalez Ryan', 85) Gonzalez, E.
('Gonzalez Ryan', 85) Gonzalez, R.
('Kody Clemens', 86) Clemens, Ko.
('Kacy Clemens', 86) Clemens, Ka.
Run Code Online (Sandbox Code Playgroud)
小智 8
尽管@Igle 的评论确实解决了这个特定问题,但我想强调的是,这是一个狭隘的解决方案,不一定适用于所有情况。Fuzzywuzzy 有多个评分器,它们使用 Levenshtein 距离算法结合不同的逻辑来比较字符串。默认评分器 fuzz.WRatio 将直接 Levenshtein 距离算法 (fuzz.ratio) 的匹配分数与其他变体进行比较,并返回所有评分器的最佳匹配。还有更多的东西,包括从不同方法加权得分的附加逻辑,如果你有兴趣,我建议查看fuzz.WRatio 的源代码。
要查看在您的情况下发生了什么,您可以通过稍微调整代码的最后几行来比较评分者所有选择的分数:
对于 token_set_ratio:
for i in names:
s = process.extract(i, choices,scorer=fuzz.token_set_ratio)
print(s, i)
[('Gonzalez Ryan', 89), ('Gonzalez Eddy', 89), ('Kody Clemens', 27), ('Kacy Clemens', 27)] Gonzalez, E.
[('Gonzalez Ryan', 89), ('Gonzalez Eddy', 89), ('Kody Clemens', 27), ('Kacy Clemens', 27)] Gonzalez, R.
[('Kody Clemens', 91), ('Kacy Clemens', 82), ('Gonzalez Ryan', 26), ('Gonzalez Eddy', 26)] Clemens, Ko.
[('Kacy Clemens', 91), ('Kody Clemens', 82), ('Gonzalez Ryan', 35), ('Gonzalez Eddy', 26)] Clemens, Ka.
Run Code Online (Sandbox Code Playgroud)
对于 token_sort_ratio:
for i in names:
s = process.extract(i, choices,scorer=fuzz.token_sort_ratio)
print(s, i)
[('Gonzalez Eddy', 87), ('Gonzalez Ryan', 70), ('Kody Clemens', 27), ('Kacy Clemens', 27)] Gonzalez, E.
[('Gonzalez Ryan', 87), ('Gonzalez Eddy', 70), ('Kody Clemens', 27), ('Kacy Clemens', 27)] Gonzalez, R.
[('Kody Clemens', 91), ('Kacy Clemens', 82), ('Gonzalez Ryan', 26), ('Gonzalez Eddy', 26)] Clemens, Ko.
[('Kacy Clemens', 91), ('Kody Clemens', 82), ('Gonzalez Ryan', 35), ('Gonzalez Eddy', 26)] Clemens, Ka.
Run Code Online (Sandbox Code Playgroud)
尽管 token_sort_ratio 显示出明显的获胜匹配,但 token_set_ratio 返回更高的分数,这就是 fuzz.WRatio 选择它返回的结果的方式。另一个主要问题是,当您有如此相似的查询和选择时,比较它们的顺序开始变得重要。例如,当我运行与上面完全相同的代码,但颠倒选择列表的顺序时,我们会得到“Gonzalez Eddy”:
for i in names:
s = process.extract(i, choices[::-1],scorer=fuzz.token_set_ratio)
print(s, i)
[('Gonzalez Eddy', 89), ('Gonzalez Ryan', 89), ('Kacy Clemens', 27), ('Kody Clemens', 27)] Gonzalez, E.
[('Gonzalez Eddy', 89), ('Gonzalez Ryan', 89), ('Kacy Clemens', 27), ('Kody Clemens', 27)] Gonzalez, R.
[('Kody Clemens', 91), ('Kacy Clemens', 82), ('Gonzalez Eddy', 26), ('Gonzalez Ryan', 26)] Clemens, Ko.
[('Kacy Clemens', 91), ('Kody Clemens', 82), ('Gonzalez Ryan', 35), ('Gonzalez Eddy', 26)] Clemens, Ka.
Run Code Online (Sandbox Code Playgroud)
我猜测正确的匹配实际上有更高的分数,但 'Eddy' 和 'Ryan' 足够接近,所以两轮比赛的最终分数都相同。
我过去处理类似问题的方法:
| 归档时间: |
|
| 查看次数: |
2393 次 |
| 最近记录: |