应用模糊匹配并获取 ID 列,其中包含每个匹配项的分数矩阵
Apply fuzzy matching and get ID columns with matrix of scores for each match
我有 2 个 pandas 数据框,我想根据其中一列进行模糊匹配。一个约 5000 行的数据框(参考数据框)包含具有相似 ID 的名称的别名,我想将其与约 1500 行具有 ID 的另一个数据框(外部)匹配。
所以对于每场比赛,我都会得到模糊分数,然后决定我想使用哪个分数作为两个数据帧之间的最佳匹配。下面的示例中使用了两个数据帧的子集。
import pandas as pd
from fuzzywuzzy import fuzz
#Reference data frame
aka_df = pd.DataFrame({"grp_id":['M-00353','M-00353','M-00353','M-00538','M-00538','M-00160','M-00160','M-00160','M-00509','M-00509','M-00509','M-00509'],
"name": ['Buatan I Mill','Inti Indosawit Subur (PKS Buatan I)','Pt Inti Indosawit Subur Buatan I','Batang Kulim','Musim Mas - Batang Kulim','Hindoli (Sungai Lilin)','Hindoli (Pks Sei Lilin)','PT Hindoli',
'Agrowiratama Sukajadi Sawit Mekar 1','PKS PT. Sukajadi Sawit Mekar','Sukajadi Sawit Mekar','Sukajadi Sawit Mekar 1']})
# External data frame
ext_df = pd.DataFrame({"uml_id": ['P021','P054','P058','P106'],
"mill_name": ['Pt Inti Indosawit Subur - Buatan I','Pt. Musim Mas - Pks Batang Kulim', 'Cargill - Hindoli', 'Pks Pt. Sukajadi Sawit Mekar']})
compare = pd.MultiIndex.from_product([aka_df['name'],ext_df['mill_name']]).to_series()
def metrics(tup):
return pd.Series([fuzz.ratio(*tup)],['ratio'])
# Create df
compare_df = compare.apply(metrics)
# Reshaping data frame
merge_df = compare_df.reset_index()
unstack_df = merge_df.groupby(['level_0','level_1'])[ 'ratio'].mean().unstack('level_1')
我对比较 2 个数据帧的代码的参考来自 问题。它确实大致给了我我需要的是:
但是,匹配矩阵中我需要的更关键的列是来自两个数据帧的 ID,如下所示。
我对 python 还是个新手,我相信这很容易做到,但非常感谢对此的一些指导。
您可以在传递给 apply()
的函数中使用 merge()
和字典理解:
import pandas as pd
from fuzzywuzzy import process,fuzz
def get_matches(x):
matches = process.extract(x['name'], ext_df['mill_name'], scorer=fuzz.ratio)
return pd.Series({ext_df.iloc[i[2]]['uml_id']: i[1] for i in matches})
aka_df.merge(aka_df.sort_values('name').apply(get_matches, axis=1), left_index=True, right_index=True)
产量:
grp_id name P021 P054 P058 P106
0 M-00353 Buatan I Mill 34 36 27 29
1 M-00353 Inti Indosawit Subur (PKS Buatan I) 91 48 27 32
2 M-00353 Pt Inti Indosawit Subur Buatan I 97 50 29 40
3 M-00538 Batang Kulim 30 55 28 15
4 M-00538 Musim Mas - Batang Kulim 38 86 34 23
5 M-00160 Hindoli (Sungai Lilin) 36 15 37 33
6 M-00160 Hindoli (Pks Sei Lilin) 32 37 36 32
7 M-00160 PT Hindoli 36 33 59 26
8 M-00509 Agrowiratama Sukajadi Sawit Mekar 1 35 15 12 70
9 M-00509 PKS PT. Sukajadi Sawit Mekar 39 30 18 100
10 M-00509 Sukajadi Sawit Mekar 33 19 11 83
11 M-00509 Sukajadi Sawit Mekar 1 36 22 15 80
此外,这里有一个有用的 link,它提供了对不同 fuzzywuzzy
评分算法的一些见解。
我有 2 个 pandas 数据框,我想根据其中一列进行模糊匹配。一个约 5000 行的数据框(参考数据框)包含具有相似 ID 的名称的别名,我想将其与约 1500 行具有 ID 的另一个数据框(外部)匹配。
所以对于每场比赛,我都会得到模糊分数,然后决定我想使用哪个分数作为两个数据帧之间的最佳匹配。下面的示例中使用了两个数据帧的子集。
import pandas as pd
from fuzzywuzzy import fuzz
#Reference data frame
aka_df = pd.DataFrame({"grp_id":['M-00353','M-00353','M-00353','M-00538','M-00538','M-00160','M-00160','M-00160','M-00509','M-00509','M-00509','M-00509'],
"name": ['Buatan I Mill','Inti Indosawit Subur (PKS Buatan I)','Pt Inti Indosawit Subur Buatan I','Batang Kulim','Musim Mas - Batang Kulim','Hindoli (Sungai Lilin)','Hindoli (Pks Sei Lilin)','PT Hindoli',
'Agrowiratama Sukajadi Sawit Mekar 1','PKS PT. Sukajadi Sawit Mekar','Sukajadi Sawit Mekar','Sukajadi Sawit Mekar 1']})
# External data frame
ext_df = pd.DataFrame({"uml_id": ['P021','P054','P058','P106'],
"mill_name": ['Pt Inti Indosawit Subur - Buatan I','Pt. Musim Mas - Pks Batang Kulim', 'Cargill - Hindoli', 'Pks Pt. Sukajadi Sawit Mekar']})
compare = pd.MultiIndex.from_product([aka_df['name'],ext_df['mill_name']]).to_series()
def metrics(tup):
return pd.Series([fuzz.ratio(*tup)],['ratio'])
# Create df
compare_df = compare.apply(metrics)
# Reshaping data frame
merge_df = compare_df.reset_index()
unstack_df = merge_df.groupby(['level_0','level_1'])[ 'ratio'].mean().unstack('level_1')
我对比较 2 个数据帧的代码的参考来自
但是,匹配矩阵中我需要的更关键的列是来自两个数据帧的 ID,如下所示。
我对 python 还是个新手,我相信这很容易做到,但非常感谢对此的一些指导。
您可以在传递给 apply()
的函数中使用 merge()
和字典理解:
import pandas as pd
from fuzzywuzzy import process,fuzz
def get_matches(x):
matches = process.extract(x['name'], ext_df['mill_name'], scorer=fuzz.ratio)
return pd.Series({ext_df.iloc[i[2]]['uml_id']: i[1] for i in matches})
aka_df.merge(aka_df.sort_values('name').apply(get_matches, axis=1), left_index=True, right_index=True)
产量:
grp_id name P021 P054 P058 P106
0 M-00353 Buatan I Mill 34 36 27 29
1 M-00353 Inti Indosawit Subur (PKS Buatan I) 91 48 27 32
2 M-00353 Pt Inti Indosawit Subur Buatan I 97 50 29 40
3 M-00538 Batang Kulim 30 55 28 15
4 M-00538 Musim Mas - Batang Kulim 38 86 34 23
5 M-00160 Hindoli (Sungai Lilin) 36 15 37 33
6 M-00160 Hindoli (Pks Sei Lilin) 32 37 36 32
7 M-00160 PT Hindoli 36 33 59 26
8 M-00509 Agrowiratama Sukajadi Sawit Mekar 1 35 15 12 70
9 M-00509 PKS PT. Sukajadi Sawit Mekar 39 30 18 100
10 M-00509 Sukajadi Sawit Mekar 33 19 11 83
11 M-00509 Sukajadi Sawit Mekar 1 36 22 15 80
此外,这里有一个有用的 link,它提供了对不同 fuzzywuzzy
评分算法的一些见解。