在 2 pandas 数据帧中执行模糊匹配

Perform Fuzzy Matching in 2 pandas dataframe

我有两个行号不同的数据框,其中包含有关玩家的信息。第一个有我需要的所有名字。

df1 = pd.DataFrame({'Player': ["John Sepi", 'Zan Fred', 'Mark Daniel', 'Adam Pop', 'Paul Sepi', 'John Hernandez', 'Price Josiah', 'John Hernandez', 'Adam Pop'], 
                    'Team': ['A', 'C', 'E', 'C', 'B', 'D', 'B', 'A', 'D']})

另一个数据框缺少一些球员,但有一个年龄列。某些情况下玩家的名字差异较小。

df2 = pd.DataFrame({'Player': ["John Sepi", 'Mark A. Daniel', 'John Hernandez', 'Price Josiah', 'John Hernandez', 'Adam Pop'], 
                    'Team': ['A', 'E', 'D', 'B', 'A', 'D'],
                   'Age': [22, 21, 26, 18, 19, 25]})

等号是不同的人,因此我需要同时匹配球员和球队。我想创建一个新的数据框,其中包含第一个数据框的所有名称以及第二个数据框的相应年龄。如果第二个缺少玩家,请完成具有恒定值的新数据框(例如 XX 年,可以是任何年龄……只是为了说明)。最终数据框:

print(final_df)
           Player Team  Age
0       John Sepi    A   22
1        Zan Fred    C   XX
2     Mark Daniel    E   21
3        Adam Pop    C   XX
4       Paul Sepi    B   XX
5  John Hernandez    D   26
6    Price Josiah    B   18
7  John Hernandez    A   19
8        Adam Pop    D   25

这是一种方法:

df1 = df1.merge(df2,how='left', on=['Players','Team']).fillna(20)

您可以使用 fuzzywuzzy 库的文本匹配功能与 python 中的 pandas 函数混合使用。

首先,导入以下库:

import pandas as pd
import numpy as np
from fuzzywuzzy import fuzz
from fuzzywuzzy import process

您可以使用 fuzzywuzzy python 库的文本匹配功能:

#get list of unique teams existing in df1
lst_teams = list(np.unique(np.array(df1['Team'])))
#define arbitrary threshold
thres = 70
#for each team match similar texts
for team in lst_teams:
    #iterration on dataframe filtered by team
    for index, row in df1.loc[df1['Team']==team].iterrows():
        #get list of players in this team
        lst_player_per_team = list(np.array(df2.loc[df2['Team']==team]['Player']))
        #use of fuzzywuzzy to make text matching
        output_ratio = process.extract(row['Player'], lst_player_per_team, scorer=fuzz.token_sort_ratio)
        #check if there is players from df2 in this team
        if output_ratio !=[]:
            #put arbitrary threshold to get most similar text
            if output_ratio[0][1]>thres:
                df1.loc[index, 'Age'] = df2.loc[(df2['Team']==team)&(df2['Player']==output_ratio[0][0])]['Age'].values[0]
df1 = df1.fillna('XX')

使用此代码和定义为 70 的阈值,您将得到以下结果:

print(df1)
           Player Team Age
0       John Sepi    A  22
1        Zan Fred    C  XX
2     Mark Daniel    E  21
3        Adam Pop    C  XX
4       Paul Sepi    B  XX
5  John Hernandez    D  26
6    Price Josiah    B  18
7  John Hernandez    A  19
8        Adam Pop    D  25

可以移动阈值以提高两个数据帧之间文本匹配能力的准确性。

请注意,使用 .iterrows() 时应小心,因为不建议在数据帧上进行迭代。

您可以在此处查看 fuzzywuzzy 文档 https://pypi.org/project/fuzzywuzzy/