拓展vlookup的difflib模糊匹配

背景

手里头有两份excel数据,一份是大表,一份是小表。其中大表名为匹配表机构.xlsx,有20000多个小区名称和对应的租金坪效字段,小表名为待匹配表.xlsx,只有一部分小区名称,现在要为小表中这些小区匹配出租金坪效值。本来想用excel的vlookup()函数匹配一番,发现匹配效果不好,因为两份数据来源不同,小区命名规则略有不同,最后只匹配出6层,有些因为小区一点点差别导致匹配补上,比如“中冶·尚城”,而大表里面有一个“中冶尚城”,两者差别仅仅存在中间一点,一个多了“·”,一个少了“·”,其实两者在实际中是表示同一个小区,此时vlookup没法匹配,于是琢磨着用difflib模块进行模糊的匹配。

待匹配里面某小区名可能与大表里面好几个相似的小区名称,其中vlookup只能匹配出完全一致,此时,相似度为1,那现在把相似度设置低一点,比如0.8,此时“同仁小区”就能和大表里面的“上海同仁小区”匹配上了。通过调节相似来找出最匹配的小区字段,然后给小表里面所有小区名称匹配出大表里面最相似的小区名称,通过大表的小区名称再来匹配对应的租金坪效值。完整代码如下

拓展vlookup的difflib模糊匹配_数据

完整代码

# -*- coding: utf-8 -*-
"""
project_name:excel模糊匹配
@author: 帅帅de三叔
Created on Wed Aug 21 13:12:09 2019
"""
import pandas as pd #数据分析模块
import difflib #导入文本对比模块
origin_data=pd.read_excel("匹配表机构.xlsx",index_col='id') #读取匹配库数据
target_data=pd.read_excel("待匹配表.xlsx",index_col='id') #读取待匹配数据
pool_item=origin_data['key'] #匹配库
search_item=target_data['key'] #待匹配目标
print(len(pool_item),len(search_item))

def get_closest(str,sequences): #定义获取最近似函数,该函数实现从sequences找出与str最相近的字符串返回,并给出相似度量
result=difflib.get_close_matches(str,sequences,n=1,cutoff=0.3)[0] #get_close_matches返回一个相似列表,并按照相似度排列,第一个为最佳匹配
ratio=difflib.SequenceMatcher(None,str,result).ratio() #计算str和result的相似度
print(str,result,ratio) #测试匹配
return result,ratio

target=[] #用来存最佳匹配字符串
ratios=[] #用来存放相似度
for item in search_item: #对待匹配目标进行循环
target.append(get_closest(item,pool_item)[0]) #追加最佳匹配值
ratios.append(get_closest(item,pool_item)[1]) #追加相似度

match={"原小区名":search_item,"匹配小区名":target,"相似度":ratios} #字典化
match=pd.DataFrame(match) #数据框化
match.to_excel("匹配结果_机构.xlsx") #保存匹配结果

代码解读

主要用到difflib模块,该模块主要用来区分两个文本的相似性,并给出文本的相似度量,具体实现过程定义了 get_closest() 函数,该函数调用了difflib.get_close_matches() 内置函数找出最佳匹配小区名称,并且调用difflib.SequenceMatcher(None,str,result).ratio() 函数给出衡量匹配好坏的相似度。有了这两个关键字段,最后和原小表里面的小区名称和匹配出来的大表小区名称以及相似度三个字段构成新的数据框,写入到 “匹配结果_机构.xlsx”,之后就可以用vlookup函数来做租金坪效匹配了。

错误代码

如果程序运行出现如下错误代码,说明原数据里面有空值,将其删除即可,或者用pandas 把空值填充。

File "D:\Python35\lib\difflib.py", line 726, in get_close_matches
if s.real_quick_ratio() >= cutoff and \
File "D:\Python35\lib\difflib.py", line 683, in real_quick_ratio
la, lb = len(self.a), len(self.b)
TypeError: object of type 'float' has no len()

拓展vlookup的difflib模糊匹配_数据_02