如何在Pandas中动态自动识别并标准化相似出版商名称
处理DataFrame中出版商名称的自动标准化问题
针对大规模DataFrame中出版商名称的变体标准化问题,以下是几种高效的动态处理方案:
第一步:基础文本清洗
先统一文本格式,去除冗余信息,减少后续匹配的干扰:
import pandas as pd import re # 加载你的数据 df = pd.read_csv("your_dataset.csv") def clean_publisher(text): if pd.isna(text): return text # 统一转为小写 text = text.lower() # 移除括号及内部内容(如"(USA)") text = re.sub(r"\([^)]*\)", "", text) # 移除所有标点符号 text = re.sub(r"[^\w\s]", "", text) # 替换常见缩写 abbreviation_map = { r"\bpubl\.\b": "publishing", r"\bco\b": "company", r"\binc\.\b": "incorporated", r"\bltd\.\b": "limited" } for pattern, replacement in abbreviation_map.items(): text = re.sub(pattern, replacement, text) # 去除多余空格并返回 return re.sub(r"\s+", " ", text).strip() # 生成清洗后的列 df["cleaned_publisher"] = df["publisher"].apply(clean_publisher)
第二步:基于模糊匹配的聚类标准化
利用模糊字符串匹配计算相似度,结合聚类算法自动分组变体,用组内最常见的名称作为标准名:
from rapidfuzz import fuzz from sklearn.cluster import DBSCAN import numpy as np # 获取去重后的清洗名称 unique_clean = df["cleaned_publisher"].dropna().unique() # 计算相似度矩阵(Levenshtein相似度,范围0-100) similarity_matrix = np.array([[fuzz.ratio(p1, p2) for p2 in unique_clean] for p1 in unique_clean]) # 转换为距离矩阵(100 - 相似度,用于DBSCAN) distance_matrix = 100 - similarity_matrix # DBSCAN聚类:eps=20表示相似度≥80的归为一类,min_samples=1允许单个样本自成一组 dbscan = DBSCAN(eps=20, min_samples=1, metric="precomputed") cluster_labels = dbscan.fit_predict(distance_matrix) # 建立聚类到标准名称的映射:取组内出现次数最多的名称 cluster_to_standard = {} for label in np.unique(cluster_labels): group_members = unique_clean[cluster_labels == label] # 统计每个成员在原数据中的出现频次 count_stats = df[df["cleaned_publisher"].isin(group_members)]["cleaned_publisher"].value_counts() # 选频次最高的作为标准名 standard_name = count_stats.idxmax().title() cluster_to_standard[label] = standard_name # 映射回原数据,生成标准化列 def map_to_standard(text): if pd.isna(text): return text idx = np.where(unique_clean == text)[0][0] return cluster_to_standard[cluster_labels[idx]] df["standardized_publisher"] = df["cleaned_publisher"].apply(map_to_standard)
第三步:针对品牌前缀的规则优化
对于类似"Harlequin"这类品牌前缀变体,可以额外添加规则,统一归为核心品牌名:
# 从标准化结果中提取核心品牌(短名称、高频出现) core_brands = [name for name in cluster_to_standard.values() if len(name.split()) <= 2] def standardize_brand(text): if pd.isna(text): return text text_lower = text.lower() for brand in core_brands: if text_lower.startswith(brand.lower()): return brand return text # 优化标准化结果 df["standardized_publisher"] = df["standardized_publisher"].apply(standardize_brand)
注意事项
- 调整DBSCAN的
eps参数:如果变体差异大,可减小eps(比如15,对应相似度≥85);如果变体差异小,可增大eps。 - 补充缩写映射:根据你的数据中出现的缩写,在
abbreviation_map里添加更多规则。 - 手动校验小部分结果:对于聚类后的少数异常组,可手动调整映射,确保准确性。
内容的提问来源于stack exchange,提问作者Claudine U
相关产品推荐
相关产品推荐

