两个好用到爆的Python模块,建议收藏!

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

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

技术交流

技术要学会分享、交流,不建议闭门造车。一个人可以走的很快、一堆人可以走的更远。

好的文章离不开粉丝的分享、推荐,资料干货、资料分享、数据、技术交流提升,均可加交流群获取,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

方式①、添加微信号:pythoner666,备注:来自CSDN + 加群
方式②、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

前言

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

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

图片

FuzzyWuzzy库介绍

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

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

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

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

1 fuzz模块

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

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

图片

1.1 简单匹配(Ratio)

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

fuzz.ratio("河南省", "河南省")

output

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

output

80

1.2 非完全匹配(Partial Ratio)

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

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

output

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

output

100

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

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

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

output

50
fuzz.ratio('I love YOU','YOU LOVE I')

output

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

output

100
fuzz.token_sort_ratio('I love YOU','YOU LOVE I') 

output

100

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

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

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

output

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

output

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

output

100

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

process模块

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

2.1 extract提取多条数据

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

choices = ["河南省", "郑州市", "湖北省", "武汉市"]
process.extract("郑州", choices, limit=2)

output

[('郑州市', 90), ('河南省', 0)]

extract之后的数据类型是列表,即使limit=1,最后还是列表,注意和下面extractOne的区别

2.2 extractOne提取一条数据

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

process.extractOne("郑州", choices)

output

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

output

('湖北省', 45)

3. 实战应用

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

3.1 公司名称字段模糊匹配

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

图片

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

图片

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 省份字段模糊匹配

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

图片

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

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'] = mm2 = 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'] = m2return df_1from fuzzywuzzy import fuzz
from fuzzywuzzy import processdf = fuzzy_merge(data, company, '公司名称', '公司名称', threshold=90)
df

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/14640.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何修复ssh漏洞进行版本升级

目录 一、ssh低版本漏洞信息 OpenSSH GSSAPI 处理远端代码执行漏洞 OpenSSH GSSAPI认证终止信息泄露漏洞 OpenSSH X连接会话劫持漏洞 二、升级ssh版本进行修复漏洞 第一步 安装Telnet服务 第二步 重启服务 第三步 安装依赖环境 第四步 备份ssh老版本文件 第五步 导入…

【动态规划上分复盘】下降路径最小和|礼物的最大价值

欢迎 前言一、动态规划五部曲二、下降路径最小和思路:动态规划解法具体代码如下 三、礼物的最大价值思路:动态规划具体代码如下: 总结 前言 本文主要讲述动态规划思路的下降路径最小和以及礼物的最大价值两道题。 一、动态规划五部曲 1.确定状态表示&a…

python_day3_str

字符串str 按索引下标查找 str Hi, world, follow, admin print(str[0]) print(str[-1])index() str Hi, world, follow, admin print(str.index(world)) #首字母下标 print(str.index(w))字符串.replace(字符串1,字符串2):…

【Elasticsearch】初识elasticsearch

目录 初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 1.1.2.ELK技术栈 1.1.3.elasticsearch和lucene 1.1.4.为什么不是其他搜索技术? 1.1.5.总结 1.2.倒排索引 1.2.1.正向索引 1.2.2.倒排索引 1.2.3.正向和倒排 1.3.es的一些概念 1.3.1.文档…

数分面试题:赛马问题

问题一: 25匹马,一个赛道,每次可以跑5匹马,在没有计时器的情况下,怎么用最小的比赛次数知道最快的前三名 关键点:通过前面的比赛,排除掉没有悬念的马(能确定有3匹马比它快的&#…

Android studio 引入不了R包,手动引入显示红色。可以跑起来却没问题

之前在这个问题踩坑2次,遂记录一下。 问题是:工程里找不到自己包名的R,手动导入显示红色,Run起来倒是没问题 尝试过Clean,Rebuild,清缓存,重启,都没用。 最终发现是没有在 Android…

【Web3】MetaMask钱包配置

目录 主网更换测试网 私钥如何登录钱包 主网更换测试网 私钥如何登录钱包

【WebGIS初学到入职】(15)入职一年的总结与分享

题外话 看看大纲可以怎么写,问问ChatGPT: ……算了,还是随便写写吧。 所以时间过得也是有够快的,这就一年了。 平淡 入职一年,已经看到好些位女同事结婚了(男同事一个没有)。领导和同事都挺…

使用ResponseBodyAdvice返回值为String出现cannot be cast to java.lang.String异常

使用ResponseBodyAdvice返回值为String出现cannot be cast to java.lang.String异常 背景 由于项目中为了全局返回统一的JSON格式,使用ResponseBodyAdvice进行拦截,拦截的时候会将返回的信息统一一个对象返回到前端。但是有的同事将一个String的响应对象…

Nuxt3 components公共组件

1.目录结构 效果实现:写一个公共的right组件,在index和about页面同时引用它 2.index页面引入 index页面显示效果 about页面引用及效果

文件共享平台Pingvin Share

本文完成于 2 月上旬。最近正好应网友要求折腾了 ClamAV,所以翻出来一起发了,可以作为 ClamAV 的一个应用示例; 什么是 Pingvin Share ? Pingvin Share 是自托管文件共享平台,是 WeTransfer 的替代品。使用 Pingvin Sh…

【爬虫学习】1、利用get方法对豆瓣电影数据进行爬取

♥️作者:白日参商 🤵‍♂️个人主页:白日参商主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识,和大家一起努力呀!!! 🎈🎈加油! 加油&#xff01…