字符串模糊匹配在很多问题中有实际价值。比如NER或任何词条关联问题,将不规范的词条与标准词条进行链接匹配。在数据量大或包含关系复杂时,使用优秀的工具包可极大提升效率。
FuzzyWuzzy 既是这样一个可进行字符串模糊匹配的python包,根据Levenshtein Distance(也被称为Edit Distance,指两个字符串,有一个转换成另一个所需要的最少操作次数)计算字符串之间的差异。这在序列比对中也是很常用的算法。编辑距离越小,两个字符串相似度越高。
FuzzyWuzzy已更新到0.18.0 版本,目前已更名为TheFuzz,对应0.19.0版本。而目前是使用更多的则是RapidFuzz,运行速度更快,参见另一篇介绍。
安装:pip install fuzzywuzzy 或 pip install thefuzz
主要有2种用法:
适用的模糊匹配关系如下:
其中前两种方法基于字符串,大小写敏感。后两种方法基于token,大小写不敏感且忽略标点符号。
直接使用Levenshtein.ratio, 计算公式:r = (sum - dist) / sum。式中idist是类编辑距离,即编辑距离中的替换需要操作两次,sum是字符串长度和。
>>> from fuzzywuzzy import fuzz,process
>>> fuzz.ratio("this is a test", "this is a test!")
97
>>> fuzz.ratio("这是测试", "这是测验") # (8-2)/8
75
先找到最长相似子字符串,再计算其与较短字符串的相似度。返回最相似的子字符串的相似度。
>>> fuzz.partial_ratio("this is a test", "this is a test!")
100
>>> fuzz.partial_ratio("这是测试示例", "这是测验")
75
先调用 process_and_sort(s1, force_ascii, full_process=full_process),将字符串按空格切分,对token按字母顺序排序后合并为新的字符串,再进行相似度计算。
该方法要求字符串由多个词组成,如果是中文,需要提前进行分词。
>>> fuzz.ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
91
>>> fuzz.token_sort_ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
100
该方法默认partial=False,比较全长字符串,另有partial_token_sort_ratio方法可用,字符串处理后可返回最大子串相似度。
与token_sort_ratio类似,不考虑子词顺序,并且不考虑token数目。先对两个字符串s1,s2根据full_process取值进行full_process处理,之后对token去重,获取交集inters和差集(diff1to2,diff2to1),并排序。然后构建(inters_sort,inters_sort+diff1to2_sort),(inters_sort,inters_sort+diff2to1_sort),(diff1to2_sort,diff2to1_sort)3个比较集合,返回相似度最大值。
>>> fuzz.token_sort_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear")
84
>>> fuzz.token_set_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear")
100
该方法默认partial=False,比较全长字符串,另有partial_token_set_ratio方法可用,字符串处理后可返回最大子串相似度。
QRatio(Quick)似乎是为了在其他方法调用时,减少一些重复的字符串操作。
WRatio(Weighted)使用了不同的算法,在使用ratio/partial_ratio获得结果后,根据序列长度进行相似度校正。
从候选列表中,返回与目标字符串最相似的一个或指定个数,可在大规模列表中直接搜索。
默认ratio计算为fuzz.WRatio,可在scorer参数指定相似度计算方法。
>>> choices = ["Atlanta Falcons", "New York Jets", "New York Giants", "Dallas Cowboys"]
>>> process.extract("new york jets", choices, limit=2)
[('New York Jets', 100), ('New York Giants', 78)]
>>> process.extractOne("cowboys", choices)
("Dallas Cowboys", 90)
# 指定 scorer
>>> process.extractOne("System of a down - Hypnotize", songs, scorer=fuzz.token_sort_ratio)
参数:
FuzzyWuzzy提供了快速方便的字符串模糊匹配和搜索方法。一般更有用的是process模块,提供封装好的函数,可以指定fuzz模块中的不同相似度计算方法,可在大规模候选集合中找到与查询字符串最相似的结果。
字符串模糊匹配的核心是两个字符串的相似度计算,详细可参考 python-Levenshtein 库的原理和使用。
FuzzyWuzzy:https://github.com/seatgeek/fuzzywuzzy
TheFuzz:https://github.com/seatgeek/thefuzz
https://medium.com/@laxmi17sarki/string-matching-using-fuzzywuzzy-24be9e85c88d