我在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数据帧包含“ concat_name”列,该列需要与列表HKCP_list中的每个名称匹配。上面的代码花费了大约2个小时来运行,列表中的名称为6K,“ concat_name”列的名称为11K。
我必须在另一个数据集上重新运行此数据集,列表中的名称为89K,列中的名称为120K。为了加快过程,我在以下关于Stackoverflow的问题中有了一个想法
Vectorizing or Speeding up Fuzzywuzzy String Matching on PANDAS Column
在以上回答的评论之一中,建议比较具有相同第一个字母的名称。我要比较的“ 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)
上述步骤耗时1600秒,包含6K X 11K数据。 “ list_to_match”列包含每个concat_name要比较的名称列表。现在在这里,我必须再次使用list_to_match元素,并将单个元素传递到列表中,然后使用process.extract方法进行模糊字符串匹配。在与上述相同的步骤中,是否有更优雅,更快捷的方法来做到这一点?
PS:编辑此代码以添加示例,说明列表和dataframe列的外观。
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:今天进行编辑,以反映昨天错过的第二个代码段中的“:”和行
关于, 尼尔维克
答案 0 :(得分:0)
您可以尝试this function我在另一个答案中写的,不是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
参数来获得次要匹配项
答案 1 :(得分:0)
下面给出的是我用于使每个实例的列表动态比较的代码:
import fuzzywuzzy
from fuzzywuzzy import fuzz,process
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']]
if len(CP_subset)>0:
chk=process.extract(row['concat_name'],CP_subset,scorer=fuzz.token_sort_ratio)[0]
else:
chk = "No item to match"
return chk
wc_df['match']=wc_df.apply(match_func,axis=1)
end_time=time.time()
print(end_time-start_time)
上面用于6K X 11K比较的代码花费了大约2600秒,而不是问题中发布的第一段代码所花费的7000秒。