首页 > 解决方案 > 寻找一种更快的模糊字符串匹配方法

问题描述

我在python中使用fuzzywuzzy进行模糊字符串匹配。我在名为 HKCP_list 的列表中有一组名称,我将其与 pandas 列迭代匹配以获得最佳匹配。下面给出的是它的代码

import fuzzywuzzy
from fuzzywuzzy import fuzz,process

def search_func(row):
    chk = process.extract(row,HKCP_list,scorer=fuzz_token_sort_ratio)[0]
    return chk

wc_df['match']=wc_df['concat_name'].map(search_func)

wc_df 数据框包含需要与列表 HKCP_list 中的每个名称匹配的列“concat_name”。上面的代码运行了大约 2 个小时,列表中有 6K 个名称,“concat_name”列中有 11K 个名称。

我必须在另一个数据集上重新运行它,其中列表中有 89K 名称,列中有 120K 名称。为了加快这个过程,我在 Stackoverflow 上的以下问题中得到了一个想法

向量化或加速 PANDAS 列上的模糊字符串匹配

在上述答案的其中一条评论中,建议比较具有相同第一个字母的名称。我要比较的“concat_name”列是通过连接数据框中的“first_name”和“last_name”列获得的派生列。因此,我使用以下函数来匹配第一个字母(因为这是我正在考虑的令牌排序分数,所以我将 first_name 和 last_name 的第一个字母与列表中的元素进行比较)。下面给出的是代码:

wc_df['first_name_1stletter'] = wc_df['first_name'].str[0]
wc_df['last_name_1stletter'] = wc_df['last_name'].str[0]

import time
start_time=time.time()
def match_func(row):
    CP_subset=[x for x in HKCP_list if x[0]==row['first_name_1stletter'] or x[0]==row['last_name_1stletter']]
    return CP_subset
wc_df['list_to_match']=wc_df.apply(match_func,axis=1)
end_time=time.time()
print(end_time-start_time)

上述步骤使用 6K X 11K 数据耗时 1600 秒。'list_to_match' 列包含要为每个 concat_name 比较的名称列表。现在在这里我必须再次获取 list_to_match 元素并传递列表中的各个元素,并使用 process.extract 方法进行模糊字符串匹配。在与上述相同的步骤中是否有更优雅和更快的方法?

PS:编辑此内容以添加有关列表和数据框列外观的示例。

HKCp_list=['jeff bezs','michael blomberg','bill gtes','tim coook','elon musk'] 
concat_name=['jeff bezos','michael bloomberg','bill gates','tim cook','elon musk','donald trump','kim jong un', 'narendra modi','michael phelps']
first_name=['jeff','michael','bill','tim','elon','donald','kim','narendra','michael']
last_name=['bezos','bloomberg','gates','cook','musk','trump','jong un', 'modi','phelps']
import pandas as pd
df=pd.DataFrame({'first_name':first_name,'last_name':last_name,'concat_name':concat_name})

df 中“concat_name”的每一行都必须与 HKcp_list 的元素进行比较。

PS:今天编辑以反映我昨天错过的第二段代码中的“:”和行

问候,尼尔维克

标签: pythonpandasfuzzywuzzy

解决方案


你可以试试我在另一个答案中写的这个函数,不是 100% 确定它在速度方面的表现,你可以自己试试:

from fuzzywuzzy import fuzz
from fuzzywuzzy import process

# Make dataframe out of list
HKCp = pd.DataFrame({'names':HKCp_list})

# Use fuzzy_merge function
fuzzy_merge(df, HKCp, 'concat_name', 'names')

输出

  first_name  last_name        concat_name           matches
0       jeff      bezos         jeff bezos         jeff bezs
1    michael  bloomberg  michael bloomberg  michael blomberg
2       bill      gates         bill gates         bill gtes
3        tim       cook           tim cook         tim coook
4       elon       musk          elon musk         elon musk
5     donald      trump       donald trump                  
6        kim    jong un        kim jong un                  
7   narendra       modi      narendra modi                  
8    michael     phelps     michael phelps                  

请注意,您可以使用treshold参数来获得不太精确的匹配


推荐阅读