0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

两个好用到爆的Python模块 轻松解决烦恼的匹配问题

Android编程精选 来源:Android编程精选 2023-08-03 11:16 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

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

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

前言

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

最常见的一个例子就是:在进行地理可视化中,自己收集的数据只保留的缩写,比如北京,广西,新疆,西藏等,但是待匹配的字段数据却是北京市,广西壮族自治区,新疆维吾尔自治区,西藏自治区等,如下。

因此就需要有没有一种方式可以很快速便捷的直接进行对应字段的匹配并将结果单独生成一列,就可以用到FuzzyWuzzy库。

eb55a010-2d41-11ee-815d-dac502259ad0.png

FuzzyWuzzy库介绍

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

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

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

1 fuzz模块

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

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

eb7224b0-2d41-11ee-815d-dac502259ad0.png

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('IloveYOU','YOULOVEI')

output

30

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

output

100

fuzz.token_sort_ratio('IloveYOU','YOULOVEI')

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.2extractOne提取一条数据

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

process.extractOne("郑州",choices)

output

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

output

('湖北省',45)

3. 实战应用

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

3.1 公司名称字段模糊匹配

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

eb7d1ece-2d41-11ee-815d-dac502259ad0.png

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

eb92f640-2d41-11ee-815d-dac502259ad0.png

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(lambdax:process.extract(x,s,limit=limit))
df_1['matches']=m

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

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

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

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

3.2 省份字段模糊匹配

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

eba7ee4c-2d41-11ee-815d-dac502259ad0.png

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

4. 全部函数代码

#模糊匹配

deffuzzy_merge(df_1,df_2,key1,key2,threshold=90,limit=2):
"""
:paramdf_1:thelefttabletojoin
:paramdf_2:therighttabletojoin
:paramkey1:keycolumnofthelefttable
:paramkey2:keycolumnoftherighttable
:paramthreshold:howclosethematchesshouldbetoreturnamatch,basedonLevenshteindistance
:paramlimit:theamountofmatchesthatwillgetreturned,thesearesortedhightolow
dataframewithbothskeysandmatches
"""
s=df_2[key2].tolist()

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

m2=df_1['matches'].apply(lambdax:[i[0]foriinxifi[1]>=threshold][0]iflen([i[0]foriinxifi[1]>=threshold])>0else'')
df_1['matches']=m2

returndf_1

fromfuzzywuzzyimportfuzz
fromfuzzywuzzyimportprocess

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






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理器
    +关注

    关注

    68

    文章

    20154

    浏览量

    247470
  • 字符串
    +关注

    关注

    1

    文章

    594

    浏览量

    23046
  • python
    +关注

    关注

    57

    文章

    4858

    浏览量

    89617
  • 3D封装
    +关注

    关注

    9

    文章

    147

    浏览量

    28201

原文标题:两个好用到爆的 Python 模块,建议收藏!

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Python调用API教程

    两个不同系统之间的信息交互。在这篇文章中,我们将详细介绍Python调用API的方法和技巧。 一、用Requests库发送HTTP请求 使用Python调用API的第一步是发送HTTP请求,通常
    的头像 发表于 11-03 09:15 338次阅读

    锂电池生产“发热”难题?这两个模块轻松搞定!

    在锂电池生产与测试过程中,温度管理是确保品质与安全的关键环节。本文将探讨锂电池生产测试中的温度挑战,并推荐款适合的测温模块,帮助工程师更好地进行温度监测与管理,提升锂电池生产的品质与安全性。前言在
    的头像 发表于 10-10 11:38 300次阅读
    锂电池生产“发热”难题?这<b class='flag-5'>两个</b><b class='flag-5'>模块</b><b class='flag-5'>轻松</b>搞定!

    硬件SPI两个CS操作两个norflash,怎么互斥操作两个norflash?

    硬件SPI两个CS操作两个norflash,怎么互斥操作两个norflash,有一norflash被模拟成U盘,会在中断中操作spi。
    发表于 09-26 06:18

    基本半导体连获两个行业奖项

    近日,基本半导体凭借在碳化硅模块领域的突出表现,连获“国产SiC模块TOP企业奖”和“年度优秀功率器件产品奖”两个行业奖项。
    的头像 发表于 09-05 16:31 903次阅读

    科普:无源晶振的电容匹配与问题

    匹配电容并不是绝对的或者固定值,无源晶振的匹配电容一般最好选择两个一样电容,在很多的方案设计中一般常用的电容有12pF、15pF、22pPF、33pF等,大致都是一20pF量级。
    的头像 发表于 08-29 11:27 1805次阅读
    科普:无源晶振的电容<b class='flag-5'>匹配</b>与问题

    看到STM8L152用两个IO用两个或非门检测两个通断,是什么原理呢?

    图中两个按键开关是两个干簧管,为什么不直接对GND设计来检测这个干簧管通断呢? 这样设计的原理是什么?
    发表于 06-12 06:25

    200r有偿求组毕设加两个模块

    找stm32 f103c8t6单片机帮我加两个模块,一BMP280-3.3压强模块,一MQ-2烟雾
    发表于 04-26 18:17

    款推荐 | 迅为RK3568开发板4核处理器+1T算力NPU+好用到的配套资料和视频!

    款推荐 | 迅为RK3568开发板4核处理器+1T算力NPU+好用到的配套资料和视频!
    的头像 发表于 03-19 13:41 1199次阅读
    <b class='flag-5'>爆</b>款推荐 | 迅为RK3568开发板4核处理器+1T算力NPU+<b class='flag-5'>好用到</b><b class='flag-5'>爆</b>的配套资料和视频!

    运行OVModelForCausalLM Python模块时出错了,怎么解决?

    创建了一自定义 Python* 代码,类似于遵循 240-dolly-2-instruction 的 Jupyter 笔记本。 OVModelForCausalLM Python*
    发表于 03-05 06:44

    两个不同频率晶振靠的近会怎样

    晶振的振荡本质上是一种机械振动(在压电晶体层面)。当两个晶振靠得很近时,它们的机械振动可能会相互影响。一晶振的振动可能会通过电路板或者外壳等介质传递给另一晶振,从而改变另一晶振的
    的头像 发表于 01-20 13:55 2024次阅读
    <b class='flag-5'>两个</b>不同频率晶振靠的近会怎样

    如何把两个数据返回给调用函数

    函数的处理结果包含两个数据,如何把两个数据返回给调用函数? 第一种,把两个数据封装成一结构体,函数返回结构体。 调用函数的地方同样用结构体去接收函数的返回值。 第二种,把返回值保存在
    的头像 发表于 01-08 10:15 687次阅读

    两个ADS1278输出十六通道只用到DOUT1,其他的几个输出管脚都不用?

    如上图所示,U4和U3通过菊花链方式连接后的数据输出,那么这两个ADS1278输出十六通道只用到DOUT1,其他的几个输出管脚都不用??求指导...
    发表于 01-08 08:04

    两个晶体管能如何实现高效正弦波振荡?

    在电子设计中,振荡器是一重要的组件,广泛应用于信号发生、无线通信和音频设备中。一般来说,设计一稳定的正弦波振荡器往往需要运算放大器或复杂的电路结构。然而,是否可以仅用两个晶体管就轻松
    的头像 发表于 01-07 12:00 965次阅读
    <b class='flag-5'>两个</b>晶体管能如何实现高效正弦波振荡?

    ADS54J60内部有两个ADC模块,内部可以设置分别提供给两个ADC模块同频相位相差90度的采样时钟吗?

    你好,ADS54J60内部有两个ADC模块,采样时钟进入片子,内部可以设置分别提供给两个ADC模块同频相位相差90度的采样时钟?还是说提供给两个
    发表于 12-23 07:38

    利用两个元件实现 L 型网络阻抗匹配

    本文要点L型网络阻抗匹配是一简单的滤波器,由两个电抗元件组成。L型滤波器具有较宽的带宽,但在载波频率下响应速度缓慢。设计人员可以组合多个L型滤波器,实现更稳健的响应以及更高的品质因数。阻抗
    的头像 发表于 12-20 18:57 2111次阅读
    利用<b class='flag-5'>两个</b>元件实现 L 型网络阻抗<b class='flag-5'>匹配</b>