Python FuzzyWuzzy实现模糊匹配


Posted in Python onApril 28, 2022

在日常开发工作中,经常会遇到这样的一个问题:要对数据中的某个字段进行匹配,但这个字段有可能会有微小的差异。比如同样是招聘岗位的数据,里面省份一栏有的写“广西”,有的写“广西壮族自治区”,甚至还有写“广西省”……为此不得不增加许多代码来处理这些情况。

今天跟大家分享FuzzyWuzzy一个简单易用的模糊字符串匹配工具包。让你轻松解决烦恼的匹配问题!

1. 前言

在处理数据的过程中,难免会遇到下面类似的场景,自己手里头获得的是简化版的数据字段,但是要比对的或者要合并的却是完整版的数据(有时候也会反过来)

最常见的一个例子就是:在进行地理可视化中,自己收集的数据只保留的缩写,比如北京,广西,新疆,西藏等,但是待匹配的字段数据却是北京市,广西壮族自治区,新疆维吾尔自治区,西藏自治区等,如下。因此就需要有没有一种方式可以很快速便捷的直接进行对应字段的匹配并将结果单独生成一列,就可以用到FuzzyWuzzy库。

Python FuzzyWuzzy实现模糊匹配

2. FuzzyWuzzy库介绍

FuzzyWuzzy 是一个简单易用的模糊字符串匹配工具包。它依据 Levenshtein Distance 算法,计算两个序列之间的差异。

Levenshtein Distance算法,又叫 Edit Distance算法,是指两个字符串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。一般来说,编辑距离越小,两个串的相似度越大。

这里使用的是Anaconda下的jupyter notebook编程环境,因此在Anaconda的命令行中输入一下指令进行第三方库安装。

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple FuzzyWuzzy

2.1 fuzz模块

该模块下主要介绍四个函数(方法),分别为:简单匹配(Ratio)、非完全匹配(Partial Ratio)、忽略顺序匹配(Token Sort Ratio)和去重子集匹配(Token Set Ratio)

注意: 如果直接导入这个模块的话,系统会提示warning,当然这不代表报错,程序依旧可以运行(使用的默认算法,执行速度较慢),可以按照系统的提示安装python-Levenshtein库进行辅助,这有利于提高计算的速度。

Python FuzzyWuzzy实现模糊匹配

2.1.1 简单匹配(Ratio)

简单的了解一下就行,这个不怎么精确,也不常用

fuzz.ratio("河南省", "河南省")
>>> 100
>
fuzz.ratio("河南", "河南省")
>>> 80

2.1.2 非完全匹配(Partial Ratio)

尽量使用非完全匹配,精度较高

fuzz.partial_ratio("河南省", "河南省")
>>> 100

fuzz.partial_ratio("河南", "河南省")
>>> 100

2.1.3 忽略顺序匹配(Token Sort Ratio)

原理在于:以 空格 为分隔符,小写 化所有字母,无视空格外的其它标点符号

fuzz.ratio("西藏 自治区", "自治区 西藏")
>>> 50
fuzz.ratio('I love YOU','YOU LOVE I')
>>> 30

fuzz.token_sort_ratio("西藏 自治区", "自治区 西藏") 
>>> 100
fuzz.token_sort_ratio('I love YOU','YOU LOVE I') 
>>> 100

2.1.4 去重子集匹配(Token Set Ratio)

相当于比对之前有一个集合去重的过程,注意最后两个,可理解为该方法是在token_sort_ratio方法的基础上添加了集合去重的功能,下面三个匹配的都是倒序

fuzz.ratio("西藏 西藏 自治区", "自治区 西藏")
>>> 40

fuzz.token_sort_ratio("西藏 西藏 自治区", "自治区 西藏")
>>> 80

fuzz.token_set_ratio("西藏 西藏 自治区", "自治区 西藏")
>>> 100

fuzz这几个ratio()函数(方法)最后得到的结果都是数字,如果需要获得匹配度最高的字符串结果,还需要依旧自己的数据类型选择不同的函数,然后再进行结果提取,如果但看文本数据的匹配程度使用这种方式是可以量化的,但是对于我们要提取匹配的结果来说就不是很方便了,因此就有了process模块。

2.2 process模块

用于处理备选答案有限的情况,返回模糊匹配的字符串和相似度。

2.2.1 extract提取多条数据

类似于爬虫中select,返回的是列表,其中会包含很多匹配的数据

choices = ["河南省", "郑州市", "湖北省", "武汉市"]
process.extract("郑州", choices, limit=2)
>>> [('郑州市', 90), ('河南省', 0)]
# extract之后的数据类型是列表,即使limit=1,最后还是列表,注意和下面extractOne的区别

2.2.2 extractOne提取一条数据

如果要提取匹配度最大的结果,可以使用extractOne,注意这里返回的是 元组 类型, 还有就是匹配度最大的结果不一定是我们想要的数据,可以通过下面的示例和两个实战应用体会一下

process.extractOne("郑州", choices)
>>> ('郑州市', 90)

process.extractOne("北京", choices)
>>> ('湖北省', 45)

3. 实战应用

这里举两个实战应用的小例子,第一个是公司名称字段的模糊匹配,第二个是省市字段的模糊匹配

3.1 公司名称字段模糊匹配

数据及待匹配的数据样式如下:自己获取到的数据字段的名称很简洁,并不是公司的全称,因此需要进行两个字段的合并

Python FuzzyWuzzy实现模糊匹配

直接将代码封装为函数,主要是为了方便日后的调用,这里参数设置的比较详细,执行结果如下:

Python FuzzyWuzzy实现模糊匹配

3.1.1 参数讲解:

① 第一个参数df_1是自己获取的欲合并的左侧数据(这里是data变量);

② 第二个参数df_2是待匹配的欲合并的右侧数据(这里是company变量);

③ 第三个参数key1是df_1中要处理的字段名称(这里是data变量里的‘公司名称’字段)

④ 第四个参数key2是df_2中要匹配的字段名称(这里是company变量里的‘公司名称’字段)

⑤ 第五个参数threshold是设定提取结果匹配度的标准。注意这里就是对extractOne方法的完善,提取到的最大匹配度的结果并不一定是我们需要的,所以需要设定一个阈值来评判,这个值就为90,只有是大于等于90,这个匹配结果我们才可以接受

⑥ 第六个参数,默认参数就是只返回两个匹配成功的结果

⑦ 返回值:为df_1添加‘matches’字段后的新的DataFrame数据

3.1.2 核心代码讲解

第一部分代码如下,可以参考上面讲解process.extract方法,这里就是直接使用,所以返回的结果m就是列表中嵌套元祖的数据格式,样式为: [(‘郑州市’, 90), (‘河南省’, 0)],因此第一次写入到’matches’字段中的数据也就是这种格式

注意,注意: 元祖中的第一个是匹配成功的字符串,第二个就是设置的threshold参数比对的数字对象

s = df_2[key2].tolist()
m = df_1[key1].apply(lambda x: process.extract(x, s, limit=limit))    
df_1['matches'] = m

第二部分的核心代码如下,有了上面的梳理,明确了‘matches’字段中的数据类型,然后就是进行数据的提取了,需要处理的部分有两点需要注意的:

① 提取匹配成功的字符串,并对阈值小于90的数据填充空值

② 最后把数据添加到‘matches’字段

m2 = df_1['matches'].apply(lambda x: [i[0] for i in x if i[1] >= threshold][0] if len([i[0] for i in x if i[1] >= threshold]) > 0 else '')
#要理解第一个‘matches'字段返回的数据类型是什么样子的,就不难理解这行代码了
#参考一下这个格式:[('郑州市', 90), ('河南省', 0)]
df_1['matches'] = m2

return df_1

3.2 省份字段模糊匹配

自己的数据和待匹配的数据背景介绍中已经有图片显示了,上面也已经封装了模糊匹配的函数,这里直接调用上面的函数,输入相应的参数即可,代码以及执行结果如下:

Python FuzzyWuzzy实现模糊匹配

数据处理完成,经过封装后的函数可以直接放在自己自定义的模块名文件下面,以后可以方便直接导入函数名即可,可以参考将自定义常用的一些函数封装成可以直接调用的模块方法。

4. 全部函数代码

#模糊匹配

def fuzzy_merge(df_1, df_2, key1, key2, threshold=90, limit=2):
    """
    :param df_1: the left table to join
    :param df_2: the right table to join
    :param key1: key column of the left table
    :param key2: key column of the right table
    :param threshold: how close the matches should be to return a match, based on Levenshtein distance
    :param limit: the amount of matches that will get returned, these are sorted high to low
    :return: dataframe with boths keys and matches
    """
    s = df_2[key2].tolist()

    m = df_1[key1].apply(lambda x: process.extract(x, s, limit=limit))    
    df_1['matches'] = m

    m2 = df_1['matches'].apply(lambda x: [i[0] for i in x if i[1] >= threshold][0] if len([i[0] for i in x if i[1] >= threshold]) > 0 else '')
    df_1['matches'] = m2

    return df_1

from fuzzywuzzy import fuzz
from fuzzywuzzy import process

df = fuzzy_merge(data, company, '公司名称', '公司名称', threshold=90)
df

以上就是Python+FuzzyWuzzy实现模糊匹配的示例详解的详细内容!


Tags in this post...

Python 相关文章推荐
python实现的重启关机程序实例
Aug 21 Python
对于Python的Django框架使用的一些实用建议
Apr 03 Python
python使用PyGame模块播放声音的方法
May 20 Python
老生常谈python函数参数的区别(必看篇)
May 29 Python
python 递归遍历文件夹,并打印满足条件的文件路径实例
Aug 30 Python
Python基于百度AI的文字识别的示例
Apr 21 Python
使用python根据端口号关闭进程的方法
Nov 06 Python
python 图片去噪的方法示例
Jul 09 Python
Python3将数据保存为txt文件的方法
Sep 12 Python
Python grequests模块使用场景及代码实例
Aug 10 Python
Python 高效编程技巧分享
Sep 10 Python
python 下划线的多种应用场景总结
May 12 Python
PYTHON基于Pyecharts绘制常见的直角坐标系图表
PYTHON 使用 Pandas 删除某列指定值所在的行
Apr 28 #Python
详解PyTorch模型保存与加载
Apr 28 #Python
Python 图片添加美颜效果
Python 视频画质增强
python 单机五子棋对战游戏
python井字棋游戏实现人机对战
Apr 28 #Python
You might like
中国广播史趣谈 — 几个历史第一次
2021/03/01 无线电
php无限极分类实现的两种解决方法
2013/04/28 PHP
php生成excel列序号代码实例
2013/12/24 PHP
微信公众号判断用户是否已关注php代码解析
2016/06/24 PHP
使用PHP访问RabbitMQ消息队列的方法示例
2018/06/06 PHP
javascript 字符串连接的性能问题(多浏览器)
2008/11/18 Javascript
学习ExtJS border布局
2009/10/08 Javascript
Extjs表单常见验证小结
2014/03/07 Javascript
javascript 拷贝节点cloneNode()使用介绍
2014/04/03 Javascript
解决jquery版本冲突的有效方法
2014/09/02 Javascript
jQuery中add()方法用法实例
2015/01/08 Javascript
简单介绍JavaScript中字符串创建的基本方法
2015/07/07 Javascript
javascript弹出带文字信息的提示框效果
2016/07/19 Javascript
Vue 2.0中生命周期与钩子函数的一些理解
2017/05/09 Javascript
Three.js利用顶点绘制立方体的方法详解
2017/09/27 Javascript
微信小程序仿美团城市选择
2018/06/06 Javascript
Vue封装的可编辑表格插件方法
2018/08/28 Javascript
jQuery点击页面其他部分隐藏下拉菜单功能
2018/11/27 jQuery
Vue基于iview table展示图片实现点击放大
2020/08/05 Javascript
python实现闹钟定时播放音乐功能
2018/01/25 Python
Python将8位的图片转为24位的图片实现方法
2018/10/24 Python
计算机二级python学习教程(2) python语言基本语法元素
2019/05/16 Python
Python要如何实现列表排序的几种方法
2020/02/21 Python
django 解决自定义序列化返回处理数据为null的问题
2020/05/20 Python
利用纯CSS3实现动态的自行车特效源码
2017/01/20 HTML / CSS
Finishline官网:美国一家领先的运动品牌鞋类、服装零售商
2016/07/20 全球购物
培训主管岗位职责
2014/02/01 职场文书
生产厂长岗位职责
2014/02/21 职场文书
五四青年节优秀演讲稿范文
2014/05/28 职场文书
整改报告怎么写
2014/11/06 职场文书
2015年幼儿园安全工作总结
2015/05/12 职场文书
婚庆司仪开场白
2015/05/29 职场文书
干部培训简讯
2015/07/20 职场文书
《小小的船》教学反思
2016/02/18 职场文书
《我要的是葫芦》教学反思
2016/02/18 职场文书
浅谈Python numpy创建空数组的问题
2021/05/25 Python