如何根据几列进行模糊匹配合并匹配

How to do fuzzy match merge to match based on a few columns

我已经从 2 个网站上抓取了一些商店信息,因此有 2 个数据框,我想将它们合并为一个完整的数据框。 我必须通过至少 2 列(例如商店代码和名称)来匹配它们。示例数据集如下所示

store code name phone email website
A KFC 111-111-1111 asdsa@as.com aaaaa.com
A3 Mc
B1 KFC 222-222-2222
store code2 name2 phone2 email2 website2
A Kfc +1111111111 asdsa@as.com aaaaa.com
A Pizzahut
B1 KFC +2222222222 qwerty@kfc.com

我想要的可能是这样的

store code name phone email website
A KFC 111-111-1111 asdsa@as.com aaaaa.com
A Pizzahut
A3 Mc
B1 KFC +2222222222 qwerty@kfc.com

解决方法一:

如果您的数据像您声称的那样干净(示例中的名称没有拼写错误),那么您可以这样做:

# Cleaning the capitalization error
df1["name"] = df1["name"].str.lower()
df2["name"] = df2["name"].str.lower()
 
df_total = df1.append(df2,ignore_index=True)

df_total = df_total.groupby(["store code","name"]).first()

解决方案二(如果您在字符串值中有错字):

但是如果名字有错别字,想按照模糊匹配的方式合并,那么就需要这样:

  1. 我们需要这些库来帮助我们:

导入 pandas 作为 pd 将 networkx 导入为 nx 从 fuzzywuzzy 导入 fuzz 导入 itertools 从 itertools 导入排列

让我们匹配案例,这样我们就安全了:

df1["name"] = df1["name"].str.lower()
df2["name"] = df2["name"].str.lower()

那就开始匹配吧!

我们需要在数据帧 (source) 中创建两个名称的所有组合,并从中创建一个数据帧,这样我们就可以使用比 for 循环快得多的应用程序:

combs = list(itertools.product(df1["name"], df2["name"]))
combs = pd.DataFrame(combs)

然后我们对每个组合进行评分。 WRatio 会很好,但您可以使用自定义函数进行匹配:

combs['score'] = combs.apply(lambda x: fuzz.WRatio(x[0],x[1]), axis=1)

现在,让我们用它制作一个图表。我使用最低分数 90 作为标准。你可以使用最适合你的:

threshold = 90
G_name = nx.from_pandas_edgelist(combs[combs['score']>=threshold],0,1, create_using=nx.Graph)

如果名称符合匹配条件,那么它们将在我们的图表中连接起来。所以每个互连的集群代表相同的名称。有了这些信息,我们可以创建一个字典,将我们数据中单个名称的所有偏差替换为唯一的。

这段代码有点复杂。简而言之,它创建了一个数据框,其中每一行都是一个名称,而列有其变体。然后它融合数据框并创建一个字典,其中以名称的偏差为键,名称的唯一表示为值。该字典允许我们用唯一的名称替换数据框中所有有偏差的名称,以便 groupby 可以正常运行:

connected_names=pd.DataFrame()
for cluster in nx.connected_components(G_name):
    if len(cluster) != 1:
        connected_names = connected_names.append([list(cluster)])
connected_names = connected_names\
    .reset_index(drop=True)\
        .melt(id_vars=0)\
            .drop('variable', axis=1)\
                .dropna()\
                    .reset_index(drop=True)\
                        .set_index('value')

names_dict = connected_names.to_dict()[0]

现在我们有了字典。剩下的就是替换名称并使用 groupby 方法:

df1["name"] = df1["name"].replace(names_dict)
df2["name"] = df2["name"].replace(names_dict)

df_total = df1.append(df2,ignore_index=True)
    
df_total = df_total.groupby(["store code","name"]).first()