fuzzywuzzy庫是Python中的模糊匹配庫,它依據(jù) Levenshtein Distance 算法 計算兩個序列之間的差異。
Levenshtein Distance
算法,又叫Edit Distance
算法,是指兩個字符串之間,由一個轉(zhuǎn)成另一個所需的最少編輯操作次數(shù)。許可的編輯操作包括將一個字符替換成另一個字符,插入一個字符,刪除一個字符。一般來說,編輯距離越小,兩個串的相似度越大。
項目地址:https://github.com/seatgeek/fuzzywuzzy
安裝
使用 PIP 通過 PyPI 安裝
pip install fuzzywuzzy
用法
>>> from fuzzywuzzy import fuzz >>> from fuzzywuzzy import process
簡單匹配(Simple Ratio)
>>> fuzz.ratio("this is a test", "this is a test!") 97
非完全匹配(Partial Ratio)
>>> fuzz.partial_ratio("this is a test", "this is a test!") 100
忽略順序匹配(Token Sort Ratio)
>>> fuzz.ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear") 91 >>> fuzz.token_sort_ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear") 100
去重子集匹配(Token Set Ratio)
>>> fuzz.token_sort_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear") 84 >>> fuzz.token_set_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear") 100
Process
用來返回模糊匹配的字符串和相似度,以下的例子就返回了分?jǐn)?shù)最高的兩個和一個字符串。
>>> choices = ["Atlanta Falcons", "New York Jets", "New York Giants", "Dallas Cowboys"] >>> process.extract("new york jets", choices, limit=2) [('New York Jets', 100), ('New York Giants', 78)] >>> process.extractOne("cowboys", choices) ("Dallas Cowboys", 90)
你可以傳入附加參數(shù)到 extractOne
方法來設(shè)置使用特定的匹配模式并返回和目標(biāo)匹配的字符串相似度最高的字符串。
>>> process.extractOne("System of a down - Hypnotize - Heroin", songs)
('/music/library/good/System of a Down/2005 - Hypnotize/01 - Attack.mp3', 86)
>>> process.extractOne("System of a down - Hypnotize - Heroin", songs, scorer=fuzz.token_sort_ratio)
("/music/library/good/System of a Down/2005 - Hypnotize/10 - She's Like Heroin.mp3", 61
以下為實例部分:
需要將rawdata sheet中的信息與addcode中的信息進(jìn)行匹配,其中caname為大類,只有大類相同才可以進(jìn)行匹配。
sp_code為rawdata 表中的主鍵,因此我們直接將主鍵匹配到結(jié)果中
代碼如下:
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
import pandas as pd
#將需要匹配的列表放入dataframe中并將需要匹配的信息拼起來
file_path=r"fuzzywuzzy test data.xlsx"
sp_rawdata=pd.read_excel(file_path,sheet_name='rawdata',index_col='sp_code')
sp_rawdata['text']=sp_rawdata['sp_webiste']+sp_rawdata['sp_channel']+sp_rawdata['sp_position']+sp_rawdata['sp_format']
tr_rawdata=pd.read_excel(file_path,sheet_name='addcode')
tr_rawdata['text']=tr_rawdata['tr_Website']+tr_rawdata['tr_Position_Channel']+tr_rawdata['tr_Format']
#獲取dataframe中cacode所有的去重后的值,并以列表的形式返回,即去重操作
sp_listtype=sp_rawdata['cacode'].unique()
tr_listtype=tr_rawdata['cacode'].unique()
scorelist=[]
rawlist=[]
#df = pd.DataFrame(columns = ["cacode", "tr_campaign_name", "tr_Website", "tr_Position_Channel", "tr_Format"])
for i in sp_listtype:
# isin()接受一個列表,判斷該列中元素是否在列表中,再根據(jù)dataframe中的布爾索引進(jìn)行篩選,類似的篩選函數(shù)還有 str.contains()
#在本例中,這個語句將cacode中屬于1,2,3的dataframe拆分成三個列表,從而匹配兩個dataframe時只會匹配cacode相同的信息
sp_data = sp_rawdata[sp_rawdata['cacode'].isin([i])]
tr_data = tr_rawdata[tr_rawdata['cacode'].isin([i])]
#按行取dataframe中的值
for row in tr_data.itertuples():
rawlist.append(row)
for text in tr_data['text']:
#忽略順序匹配并取出匹配分?jǐn)?shù)最高的值
score = process.extractOne(str(text), sp_data['text'].astype(str), scorer=fuzz.token_sort_ratio)
scorelist.append(score)
#轉(zhuǎn)換list為dataframe類型
scorecode=pd.DataFrame(scorelist)
df=pd.DataFrame(rawlist)
#修改轉(zhuǎn)變后的dataframe的字段名稱,注意這里0和1都不是字符串
scorecode=scorecode.rename(columns={0:'sp-text',1:'score',2:"add_sp_code"})
#兩個dataframe相連,axis: 需要合并鏈接的軸,0是行,1是列,這里按照列拼接
result=pd.concat([df,scorecode],axis=1)
result.to_excel(r" fuzzy mapping result.xlsx",index=False)
公眾號:Romi的雜貨鋪,更多的相關(guān)文章
源代碼及數(shù)據(jù)文件,結(jié)果文件可點(diǎn)擊https://github.com/smilecoc/smilecoc-fuzzywuzzy_test