如何根据几列进行模糊匹配合并匹配
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()
解决方案二(如果您在字符串值中有错字):
但是如果名字有错别字,想按照模糊匹配的方式合并,那么就需要这样:
- 我们需要这些库来帮助我们:
导入 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()
我已经从 2 个网站上抓取了一些商店信息,因此有 2 个数据框,我想将它们合并为一个完整的数据框。 我必须通过至少 2 列(例如商店代码和名称)来匹配它们。示例数据集如下所示
store code | name | phone | 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 | 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()
解决方案二(如果您在字符串值中有错字):
但是如果名字有错别字,想按照模糊匹配的方式合并,那么就需要这样:
- 我们需要这些库来帮助我们:
导入 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()