Python+FuzzyWuzzy实现模糊匹配的示例详解

目录
  • 1. 前言
  • 2. FuzzyWuzzy库介绍
    • 2.1 fuzz模块
    • 2.2 process模块
  • 3. 实战应用
    • 3.1 公司名称字段模糊匹配
    • 3.2 省份字段模糊匹配
  • 4. 全部函数代码

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

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

1. 前言

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

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

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 公司名称字段模糊匹配

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

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

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'] = 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实现模糊匹配的示例详解的详细内容,更多关于Python FuzzyWuzzy模糊匹配的资料请关注我们其它相关文章!

(0)

相关推荐

  • 使用Python完成公司名称和地址的模糊匹配的实现

    github主页 导入: >>> from fuzzywuzzy import fuzz >>> from fuzzywuzzy import process 1) >>> fuzz.ratio("this is a test", "this is a test!") out 97 >>> fuzz.partial_ratio("this is a test", "

  • Python3中FuzzyWuzzy库实例用法

    万事万物都有自身存在的道理,虽然在python中有些代码我们并不常见.经常会觉得不是常用,就可以避之,但是大家好像都遗忘了一件事情,就是"真理都掌握在少数人手中",往往最不起眼的库,经常能给我们带来高效率,最适宜的使用过程,好啦,下面就给大家讲下FuzzyWuzzy库啦~ 前置条件 Python3 python-Levenshtein 安装方法: 通过Pip安装 pip install fuzzywuzzy 导入库: fromfuzzywuzzy import fuzz 做个简单的测试

  • Python+FuzzyWuzzy实现模糊匹配的示例详解

    目录 1. 前言 2. FuzzyWuzzy库介绍 2.1 fuzz模块 2.2 process模块 3. 实战应用 3.1 公司名称字段模糊匹配 3.2 省份字段模糊匹配 4. 全部函数代码 在日常开发工作中,经常会遇到这样的一个问题:要对数据中的某个字段进行匹配,但这个字段有可能会有微小的差异.比如同样是招聘岗位的数据,里面省份一栏有的写“广西”,有的写“广西壮族自治区”,甚至还有写“广西省”……为此不得不增加许多代码来处理这些情况. 今天跟大家分享FuzzyWuzzy一个简单易用的模糊字符

  • python计算机视觉opencv卡号识别示例详解

    目录 一.模板预处理 1.将模板设置为二值图 2.检测模板的轮廓 3.对模板轮廓排序,并将数字和轮廓一一对应,以字典存储 4.备注 二.图片预处理 1.初始化卷积核 2.图片预处理第一部分 3.图像预处理第二部分 三.轮廓处理 1.大轮廓过滤 2.小轮廓分割 模板图片如下: 需识别的图片如下: 一.模板预处理 1.将模板设置为二值图 2.检测模板的轮廓 3.对模板轮廓排序,并将数字和轮廓一一对应,以字典存储 排序的函数如下: 排序并存储: 4.备注 ①每一个数字对应的是二值图截出来的那个数字图的

  • Python MySQL数据库基本操作及项目示例详解

    目录 一.数据库基础用法 二.项目:银行管理系统 1.进行初始化操作 2.登录检查,并选择操作 3.加入查询功能 4.加入取钱功能 5.加入存钱功能 一.数据库基础用法 要先配置环境变量,然后cmd安装:pip install pymysql 1.连接MySQL,并创建wzg库 #引入decimal模块 import pymysql #连接数据库 db=pymysql.connect(host='localhost',user='root',password='1234',charset='ut

  • Python实现解析yaml配置文件的示例详解

    目录 楔子 字典 数组 标量 引用 生成 yaml 文件 楔子 前面我们介绍了 ini 格式的配置文件,本次来看看 yaml,它的表达能力相比 ini 更加的强大.yaml 文件以 .yml 结尾,在介绍它的语法结构之前我们先来看看 yaml 的一些基本规则. 大小写敏感: 使用缩进表示层级关系,并且缩进只能用空格.不可以使用 tab 键.缩进的空格数目不重要,只要相同层级的元素左侧对齐即可: # 表示注释,# 到行尾的所有字符都会被忽略: yaml 支持的数据结构有以下三种: 字典:键值对的集

  • python进阶collections标准库使用示例详解

    目录 前言 namedtuple namedtuple的由来 namedtuple的格式 namedtuple声明以及实例化 namedtuple的方法和属性 OrderedDict popitem(last=True) move_to_end(key, last=True) 支持reversed 相等测试敏感 defaultdict 小例子1 小例子2 小例子3 Counter对象 创建方式 elements() most_common([n]) 应用场景 deque([iterable[,

  • 对python 生成拼接xml报文的示例详解

    最近临时工作要生成xml报名,通过MQ接口发送.简单小程序. 自增长拼成xml报文 Test_001.py # encoding=utf-8 import time orderId = '' s1= "\n" # for ID in range(1,5): item1 = "<item>" + \ "<orderID>" + str(ID) + "</orderID>" + \ "

  • Python中bisect的用法及示例详解

    bisect是python内置模块,用于有序序列的插入和查找. 查找: bisect(array, item) 插入: insort(array,item) 查找 import bisect a = [1,4,6,8,12,15,20] position = bisect.bisect(a,13) print(position) # 用可变序列内置的insert方法插入 a.insert(position,13) print(a) 输出: 5 [1, 4, 6, 8, 12, 13, 15, 2

  • shell模糊匹配与正则详解

    前言: 正则可以实现一些简单的功能,并用在脚本中,如检测ip地址是否符合规范,检测文件名是否符合规范等等. 正则表达式 正则表达式主要是用来描述一个句法规则的模式.其实说的通俗一点,就是利用字符和元字符的组合,对一些符合既定句法的模式进行模糊匹配.它的主要功能是文本查询和字符串操作. 正则表达式的基本元素包括普通字符和元字符,在Linux shell里面,常用的正则表达式元字符集为:S={*  .  ^  $  []  \  \<\>  \{\}  \{n,\}  \{n,m\} },每一个元

  • python实现三壶谜题的示例详解

    前言 有一个充满水的8品脱的水壶和两个空水壶(容积分别是5品脱和3品脱).通过将水壶完全倒满水和将水壶的水完全倒空这两种方式,在其中的一个水壶中得到4品脱的水. 一.算法思想 算法分析 采用的算法思想是将某个时刻水壶中水的数量看作一个状态,用一个长度为3的数组表示. 初始状态便为[8,0,0],再拓展他的下一结点的可能结构. 若下一结点的结构已经被拓展过了便放弃,若没有拓展过则加入拓展列表(open_list)中.然后递归上述操作. 直到拓展列表(open_list)为空或者找到目标为止. 思想

  • Python机器学习从ResNet到DenseNet示例详解

    目录 从ResNet到DenseNet 稠密块体 过渡层 DenseNet模型 训练模型 从ResNet到DenseNet 上图中,左边是ResNet,右边是DenseNet,它们在跨层上的主要区别是:使用相加和使用连结. 最后,将这些展开式结合到多层感知机中,再次减少特征的数量.实现起来非常简单:我们不需要添加术语,而是将它们连接起来.DenseNet这个名字由变量之间的"稠密连接"而得来,最后一层与之前的所有层紧密相连.稠密连接如下图所示: 稠密网络主要由2部分构成:稠密块(den

随机推荐