当前位置: 首页 > 后端技术 > Python

Python中一个模糊匹配的神奇库:FuzzyWuzzy

时间:2023-03-25 22:00:42 Python

在日常的开发工作中,我们经常会遇到这样的问题:要匹配数据中的某个字段,但是这个字段可能存在细微的差异。比如同一个招聘信息,在省一栏中,有的写“广西”,有的写“广西壮族自治区”,有的甚至写“广西省”。为此,必须添加大量代码来处理这些情况。今天给大家分享一个简单易用的模糊字符串匹配工具包FuzzyWuzzy。让你轻松解决恼人的配对问题!一、前言在数据处理的过程中,难免会遇到以下类似的场景。你拿到手上的是简化版的数据字段,但你要比较或合并的是完整版的数据(有时会颠倒过来)最常见的例子是:在地理可视化中,通过自己只保留简称,如北京、广西、新疆、西藏等,但要匹配的字段数据是北京、广西壮族自治区、新疆维吾尔自治区、西藏自治区等,如下。因此,有必要想办法快速方便地直接匹配相应的字段,并生成单独的一列结果,可以在FuzzyWuzzy库中使用。2.FuzzyWuzzy库介绍FuzzyWuzzy是一个易于使用的模糊字符串匹配工具包。它根据Levenshtein距离算法计算两个系列之间的差异。LevenshteinDistance算法,也称为EditDistance算法,是指两个字符串之间从一个字符串转换为另一个字符串所需的最小编辑操作次数。允许的编辑操作包括用另一个字符替换一个字符、插入一个字符和删除一个字符。一般来说,编辑距离越小,两个字符串之间的相似度就越大。这里使用的是Anaconda下的jupyternotebook编程环境,所以在Anaconda的命令行输入命令安装第三方库。pipinstall-ihttps://pypi.tuna.tsinghua.edu.cn/simpleFuzzyWuzzy2.1fuzz模块该模块主要介绍四个功能(方法),分别是:简单匹配(Ratio)、部分匹配(PartialRatio)、忽略序列匹配(TokenSortRatio)和去重子集匹配(TokenSetRatio)注意:如果直接导入该模块,系统会提示警告,当然这并不代表报错,程序可以仍然运行(使用默认算法,执行速度较慢),可以按照系统提示安装python-Levenshtein库进行辅助,有利于提高计算速度。2.1.1简单匹配(Ratio)简单理解就可以了,这个不是很准确,也不常用fuzz.ratio("河南省","河南省")>>>100>fuzz.ratio("HenanProvince","HenanProvince")>>>802.1.2PartialRatio(部分比率)尽量使用非完全匹配,准确率更高fuzz.partial_ratio("HenanProvince","HenanProvince")>>>100fuzz.partial_ratio("河南省","河南省")>>>1002.1.3IgnoreTokenSortRatio原则是:以空格为分隔符,字母全部小写,忽略空格以外的其他标点符号fuzz.ratio("西藏自治区","西藏自治区")>>>50fuzz.ratio('我爱你','你爱我')>>>30fuzz.token_sort_ratio("西藏自治区","西藏自治区")>>>100fuzz.token_sort_ratio('IloveYOU','YOULOVEI')>>>1002.1.4去重子集匹配(TokenSetRatio)相当于比对前的一个集合去重过程。注意最后两个,可以理解为这个方法在token_sort_ratio方法的基础上,增加了set去重的功能。以下三场比赛都是倒序。,"西藏自治区")>>>80fuzz.token_set_ratio("西藏自治区",《西藏自治区》)>>>100fuzzratio()函数(方法)终于得到了数字。如果要得到匹配度最高的字符串结果,需要根据自己的数据类型选择不同的函数。然后提取结果。如果看文本数据的匹配度,可以通过这种方式进行量化,但是对于我们提取匹配结果不是很方便。于是就有了处理模块2.2处理模块用于处理备选答案有限的情况,返回模糊匹配字符串和相似度。2.2.1Extract提取多条数据类似于爬虫中的select,返回一个列表,里面会包含很多匹配的数据choices=["河南省","郑州市","湖北省","武汉市"City"]process.extract("郑州",choices,limit=2)>>>[('郑州市',90),('河南省',0)]#extract后的数据类型是list,偶iflimit=1,finally还是一个列表,注意和下面的extractOne的区别2.2.2extractOne提取一条数据如果要提取匹配度最高的结果,可以使用extractOne,注意这里返回的是元组类型,匹配度最高的结果不一定是我们的你可以通过下面的例子和两个实际应用过程体会到想要的数据。extractOne("郑州",choices)>>>('郑州',90)process.extractOne("Beijing",choices)>>>('湖北省',45)3.实际应用这里举两个小例子实际应用中,一是公司名称字段的模糊匹配,二是省市字段的模糊匹配3.1公司名称字段的模糊匹配需要匹配的数据和数据样式如下:自己获取的数据字段名称很简洁,不是公司全称,所以需要将两个字段合并,直接把代码封装成一个函数,主要是方便以后调用,参数设置这里比较详细,执行结果如下:3.11参数说明:①第一个参数df_1是自己获取的待合并的左数据(这里是data变量);②第二个参数df_2是想要匹配的数据。合并右边的数据(这里是公司变量);③第三个参数key1是df_1中要处理的字段名(这里是data变量中的'公司名'字段)④第四个参数key2是df_2中要匹配的字段名(这里是'公司名'公司变量中的字段)⑤第五个参数threshold是设置提取结果匹配度的标准。注意这是extractOne方法的改进。提取出来的最大匹配度的结果不一定是我们需要的,所以我们需要设置一个阈值来判断,这个值为90,只要大于等于90,我们就可以使用这个匹配结果⑥的第六个参数,默认参数是只返回两个匹配成功的结果⑦返回值:df_1中添加'matches'字段后的新DataFrame数据3.1.2核心代码解释第一部分代码如下,大家可以参考to上面解释了process.extract方法,这里直接使用,所以返回结果m为列表中嵌套祖先的数据格式,样式为:[('郑州市',90),('HenanProvince',0)],所以第一次写入'matches'字段的数据也是这种格式注意,注意:元组中的第一个是匹配成功的字符串,第二个是匹配成功的字符串与设定阈值参数比较的数字对象s=df_2[key2].tolist()m=df_1[key1].apply(lambdax:process.extract(x,s,limit=limit))df_1['matches']=m第二部分核心代码如下,经过上面的梳理,数据类型在澄清“匹配”字段,然后提取数据。需要处理的部分有两点需要注意:①提取匹配成功的字符串,选择阈值小于90的字符串数据填充空值②最后将数据添加到“匹配”字段m2=df_1['匹配'].apply(lambdax:[i[0]foriinxifi[1]>=threshold][0]iflen([i[0]foriinxifi[1]>=threshold])>0else'')#了解第一个'matches'字段返回的数据类型是什么看起来这行代码不是难理解#参考这个格式:[('郑州市',90),('河南省',0)]df_1['matches']=m2returndf_13.2省份字段模糊匹配自己的数据和要匹配的数据。后台介绍中已经有图片,上面已经封装了模糊匹配的功能。这里可以直接调用上面的函数,输入相应的参数即可。代码及执行结果如下:Data处理完成后,封装好的函数可以直接放在你自定义的模块名文件中以后直接导入函数名就方便了。可以参考将一些常用的自定义函数封装成模块直接调用的方法4.全部函数代码#模糊匹配deffuzzy_merge(df_1,df_2,key1,key2,threshold=90,limit=2):""":paramdf_1:左表join:paramdf_2:右表join:paramkey1:左表的键列:paramkey2:右表的键列:paramthreshold:基于Levenshtein距离,匹配应该有多接近以返回匹配:paramlimit:将返回的匹配数量,这些从高到低排序:return:dataframewithbothskeysandmatches"""s=df_2[key2].tolist()m=df_1[key1].apply(lambdax:process.extract(x,s,limit=limit))df_1['matches']=mm2=df_1['matches'].apply(lambdax:[i[0]foriinxifi[1]>=threshold][0]iflen([i[0]foriinxifi[1]>=threshold])>0else'')df_1['matches']=m2returndf_1fromfuzzywuzzyimportfuzzfromfuzzywuzzyimportprocessdf=fuzzy_merge(data,company,'公司名称','公司名称',threshold=90)df想更加系统高效的学习Python,推荐一个gzh——【Python编程学习圈】,每天分享技术干货,供大家阅读学习。关注的话,可以免费领取从初学者到高级的全套Python。学习资料和教程,有兴趣的抓紧时间