You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DataFrame同列公司名模糊匹配分组异常及行数不符问题求助

问题:DataFrame同列相似公司名模糊匹配分组异常(行数膨胀+分组错误)

问题现象

  • 尝试通过模糊匹配对DataFrame同列的相似公司名称进行分组,但无法正确完成分组
  • 现有代码因生成笛卡尔积匹配,导致结果行数远多于原数据,不符合需求
  • 要求最终输出行数与原数据一致,同时完成相似公司名的正确分组

原代码

import pandas as pd
from fuzzywuzzy import fuzz

df.loc[:,'Account Name Copy'] = df['Account Name']

compare = pd.MultiIndex.from_product([df['Account Name'],
                                      df['Account Name Copy']]).to_series()

def metrics(tup):
    return pd.Series([fuzz.ratio(*tup),
                      fuzz.token_sort_ratio(*tup)],
                     ['ratio', 'token'])

compare.apply(metrics)

问题分析

原代码使用pd.MultiIndex.from_product生成所有公司名称的笛卡尔积,导致行数变为原数据行数的平方,完全偏离需求;且仅计算了匹配度,未实现分组逻辑,无法完成相似名称的归类。

解决方案(保持原数据行数+正确分组)

采用**并查集(Union-Find)**结合模糊匹配的方式,将相似公司名归为同一组,同时保证输出行数与原数据一致:

import pandas as pd
from fuzzywuzzy import fuzz
from itertools import combinations

# 并查集类:用于高效管理相似组的合并与查询
class UnionFind:
    def __init__(self, elements):
        self.parent = {elem: elem for elem in elements}
    
    def find(self, elem):
        if self.parent[elem] != elem:
            self.parent[elem] = self.find(self.parent[elem])
        return self.parent[elem]
    
    def union(self, elem1, elem2):
        root1 = self.find(elem1)
        root2 = self.find(elem2)
        if root1 != root2:
            self.parent[root2] = root1

# 1. 从原DataFrame提取唯一公司名称
unique_accounts = df["Account Name"].unique()

# 2. 初始化并查集
uf = UnionFind(unique_accounts)

# 3. 设置相似度阈值(可根据业务需求调整,示例设为80)
similarity_threshold = 80

# 4. 遍历所有名称组合,合并相似度达标组
for acc1, acc2 in combinations(unique_accounts, 2):
    # 用token_sort_ratio适配公司名(忽略单词顺序差异)
    if fuzz.token_sort_ratio(acc1, acc2) >= similarity_threshold:
        uf.union(acc1, acc2)

# 5. 为每个公司名映射到对应的组根节点(作为分组标识)
group_map = {acc: uf.find(acc) for acc in unique_accounts}

# 6. 将分组标识添加回原DataFrame,保持行数一致
df["Group ID"] = df["Account Name"].map(group_map)

# 可选:将组标识替换为更友好的组名(比如组内最短名称)
# df["Group Name"] = df["Group ID"].apply(lambda x: min([k for k, v in uf.parent.items() if uf.find(k) == x], key=len))

方案说明

  • 并查集确保相似的公司名被归为同一组(如A与B相似、B与C相似,则A/B/C自动同组)
  • token_sort_ratio相比普通ratio更适合公司名匹配,能处理"ABC有限公司"和"有限公司ABC"这类顺序颠倒的相似名称
  • 阈值可灵活调整:若需更宽松的匹配可降低阈值,严格匹配则提高阈值
  • 最终输出的Group ID列会为所有相似公司名分配相同标识,原DataFrame行数完全不变

内容的提问来源于stack exchange,提问作者ss_0708

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 13:20:29