Python字典中如何将相似词汇归并到同一标准键下
基于fuzzywuzzy的相似网站名称归并方案
前置依赖安装
先安装需要的第三方库,python-Levenshtein可以加速fuzzywuzzy的相似度计算:pip install fuzzywuzzy python-Levenshtein pandas
实现逻辑
整个流程不需要复杂算法,针对短文本的网站名匹配准确率足够:
- 先做文本标准化预处理:统一大小写、移除.com/.org等通用顶级域名后缀、清理多余空格,减少无意义的字符差异对相似度计算的干扰
- 提取数据集中所有去重后的网站名称,逐个和已有分组的标准值计算文本相似度
- 相似度超过设定阈值就归到对应分组,未匹配到现有分组就新建分组
- 每个分组选出现频次最高的名称作为标准键,生成原始值到标准键的映射字典,直接用pandas的map方法给DataFrame新增列即可
可直接运行的代码
import pandas as pd from fuzzywuzzy import fuzz from collections import Counter def clean_website_name(name: str) -> str: """网站名标准化预处理""" if not isinstance(name, str): return "" name = name.lower().strip() # 移除常见顶级域名后缀 for suffix in [".com", ".org", ".net", ".edu", ".cn"]: if name.endswith(suffix): name = name[:-len(suffix)] # 合并连续空格 name = " ".join(name.split()) return name def build_site_mapping(unique_sites: list, sim_threshold: int = 88) -> dict: """ 生成原始网站名到标准名的映射字典 :param unique_sites: 数据集中所有去重后的原始网站名 :param sim_threshold: 相似度阈值,取值0-100,短文本场景建议85-92之间调整 """ # 预生成所有原始值对应的清洗后值 cleaned_cache = {raw: clean_website_name(raw) for raw in unique_sites} groups = [] # 分组结构:[组标准清洗值, 组内原始值列表] for raw_name in unique_sites: cleaned = cleaned_cache[raw_name] if not cleaned: continue match_flag = False # 遍历现有分组查找匹配项 for idx, (group_std_clean, group_raw_list) in enumerate(groups): # 用token_set_ratio计算相似度,对缺词、多后缀的场景适配更好 sim_score = fuzz.token_set_ratio(cleaned, group_std_clean) if sim_score >= sim_threshold: groups[idx][1].append(raw_name) match_flag = True break # 无匹配则新建分组 if not match_flag: groups.append([cleaned, [raw_name]]) # 生成最终映射,选组内出现频次最高的原始值转大写作为标准键 final_map = {} for _, raw_list in groups: most_common_raw = Counter(raw_list).most_common(1)[0][0] std_key = most_common_raw.upper() for raw_val in raw_list: final_map[raw_val] = std_key return final_map # 调用示例 if __name__ == "__main__": # 替换成你的实际DataFrame和网站列名 # df = pd.read_csv("your_survey_data.csv") # 测试用数据 df = pd.DataFrame({ "website": ["amazon","amzn","amazon prime","amazon.com", "amzn prim", "coursera","corsera","coursera.org","coursera.com"] }) unique_sites = df["website"].dropna().unique().tolist() site_map = build_site_mapping(unique_sites, sim_threshold=88) # 新增标准名列 df["standard_website"] = df["website"].map(site_map) print(df) print(site_map)
调优提示
- 阈值第一次设置建议先取88,跑完后打印映射字典检查结果:如果出现不同网站被错误归为一类,就调大阈值;如果同一网站的不同写法被分成多个组,就调小阈值
- 如果提前已知部分固定别名对应关系,可以在生成最终映射前手动补充到字典里,避免匹配错误
- 匹配算法优先选
fuzz.token_set_ratio,比默认的fuzz.ratio对带冗余后缀、词序颠倒、少量拼写错误的短文本匹配准确率高很多 - 数据量不大的情况下,建议生成映射后人工过一遍每个分组的结果,修正个别离谱拼写错误导致的错分,成本极低
内容的提问来源于stack exchange,提问作者aryaman
相关产品推荐
相关产品推荐

