python-3.x - FuzzyWuzzy 用于 Python 中非常相似的记录
问题描述
我有一个数据集,我想找到最接近的字符串匹配。为此,我以这种方式使用 FuzzyWuzzy
sol=process.extract(t,dev2,scorer=fuzz.token_sort_ratio)
其中 t 是字符串,dev2 是要比较的列表。我的问题是,有时它有非常相似的记录,而 FuzzyWuzzy 提供的选项似乎很缺乏。我已经用 token_sort、token_set、partial_token 排序和设置、ratio、partial_ratio 和 WRatio 进行了测试。
例如,该字符串Italy - Serie A
为我提供了以下 2 个最接近的匹配项。
Token_sort_ratio: (92, 'Italy - Serie D');(86, 'Italian - Serie A')
想要的显然是第二个,但逐个字符更接近第一个,这是一个不同的联盟。
这也发生在团队中。如果,假设我有一个字符串Buchtholz
,我会Buchtholz II
在得到TSV Buchtholz
.
我现在的主要猜测是尝试更重地加权几个字符的存在和缺失,比如字符串末尾的单个大写字母,所以如果字母有差异或缺失,它的权重会不那么接近。或 for()
和特殊字符。
我不知道是否有办法考虑到这一点,或者你们有更好的方法来获得真正匹配的字符串。
解决方案
相似性匹配通常需要了解正在分析的数据。即这不仅仅是单轮匹配。我建议你通过更多的匹配步骤来传递你的结果,从具有低截止分数的包容/乐观方法(如 token_set_ratio)开始,并朝着具有更高截止分数的更排斥/悲观方法努力,直到你有一个明确的赢家。如果您对正在分析的文本有更多了解,您甚至可以在进行时修改字符串。
在我处理的一个案例中,我对货物移动描述进行了相似性匹配。在描述中,数字序列比文本更重要。例如,在寻找“SLURRY VALVE 250MM RAGMAX 2000”的匹配项时,字符串的 250 和 2000 部分很重要,否则我会得到“SLURRY VALVE 50MM RAGMAX 2000”作为最佳匹配,而不是“VALVE B/F 250MM,RAGMAX” 250RAG2000 RAGON”这是一个更好的结果。
我把相似度匹配过程分为两个步骤: 1. 使用乐观匹配记分器(token_set_ratio)得到一堆相似匹配 2. 得到这些结果的数字序列,并通过更严格的记分器(token_sort_ratio)进行另一轮匹配)。在上面显示的示例中,这样做给了我更好的结果。
以下是一些可能有帮助的代码块:
这是一个从序列中获取数字的函数。(在您的情况下,您可能会使用它来从字符串中排除数字?)
def get_numbers_from_string(description):
numbers = ''.join((ch if ch in '0123456789.-' else ' ') for ch in description)
numbers = ' '.join([nr for nr in numbers.split()])
return numbers
这是我用来将描述匹配通过两轮的代码的一部分:
try:
# get close match from goods move that has material numbers
df_material = pd.DataFrame(process.extract(description,
corpus_material,
scorer=fuzz.token_set_ratio),
columns=['Similar Text','Score']
)
if df_material['Score'][df_material['Score']>=cut_off_accuracy_materials].count()>=1:
similar_text = df_material['Similar Text'].iloc[0]
score = df_material['Score'].iloc[0]
if nr_description_numbers>4:
# if there are multiple matches found, then get best number combination match
df_material = df_material[df_material['Score']>=cut_off_accuracy_materials]
new_corpus = list(df_material['Similar Text'])
new_corpus = np.vectorize(get_numbers_from_string)(new_corpus)
df_material['numbers'] = new_corpus
df_numbers = pd.DataFrame(process.extract(description_numbers,
new_corpus,
scorer=fuzz.token_sort_ratio),
columns=['numbers','Score']
)
similar_text = df_material['Similar Text'][df_material['numbers']==df_numbers['numbers'].iloc[0]].iloc[0]
nr_score = df_numbers['Score'].iloc[0]
希望它有帮助,祝你好运
推荐阅读
- excel - 如何透视表异常表
- android - 不能同时使用 Fabulous 和 Android.Speech
- kotlin - 从“Where x is not null”的查询结果构建对象时,是否仍然可以在属性“x”上获得“NullPointerException”
- nginx - Nginx 使用上游变量删除位置路径
- php - PHP删除重复的数组值
- javascript - Eslint Jsdoc 插件未执行
- python - 用于 uvicorn 的 unix 套接字上的 Nginx 反向代理不起作用
- vuejs2 - VUE路由重定向未从其他页面关闭模式
- javascript - 如何在 HTML5 样板中添加 require()
- html - Edge 中嵌入 PDF 的默认缩放