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

基于90%相似度的Pandas字符串分组方案求助(40万行数据)

针对40万行Pandas DataFrame的近似字符串分组方案

核心思路

针对大规模数据的近似字符串分组,核心是减少不必要的相似度计算,同时利用C加速的模糊匹配库(如RapidFuzz)提升效率,避免全量两两比对。以下两种方案可高效适配40万行数据的需求:


方案一:RapidFuzz + DBSCAN聚类

适合唯一字符串数量中等(如1万-10万)的场景,通过聚类将相似字符串归为一组,再为每组指定代表(频次最高的字符串)。

步骤与代码

  1. 先安装依赖:
pip install rapidfuzz pandas scikit-learn numpy
  1. 完整实现代码:
import pandas as pd
from rapidfuzz import fuzz
from sklearn.cluster import DBSCAN
import numpy as np

# 加载数据(示例数据替换为你的DataFrame)
data = pd.DataFrame(data=["Apple", "Apple", "apple", "appel", "aple", "Orange", "Banana"], columns=["Fruits"], dtype="str")

# 1. 提取唯一字符串并统计频次,减少计算量
unique_fruits = data["Fruits"].value_counts().reset_index()
unique_fruits.columns = ["Fruit", "Count"]
fruit_list = unique_fruits["Fruit"].tolist()

# 2. 生成相似度转距离的矩阵(1 - 相似度/100,DBSCAN用距离聚类)
# 用rapidfuzz的cdist批量计算,效率远高于手动循环
from rapidfuzz import process
distance_matrix = 1 - np.array(process.cdist(fruit_list, fruit_list, scorer=fuzz.ratio)) / 100

# 3. DBSCAN聚类:eps=0.1对应90%相似度,min_samples=1确保单个字符串也成组
dbscan = DBSCAN(eps=0.1, min_samples=1, metric="precomputed")
unique_fruits["Cluster"] = dbscan.fit_predict(distance_matrix)

# 4. 为每个聚类分配代表(取组内频次最高的字符串)
cluster_reps = unique_fruits.groupby("Cluster").apply(
    lambda x: x.loc[x["Count"].idxmax(), "Fruit"]
).reset_index(name="Representative")

# 5. 映射回原数据并统计最终结果
unique_fruits = unique_fruits.merge(cluster_reps, on="Cluster")
data["Grouped_Fruit"] = data["Fruits"].map(unique_fruits.set_index("Fruit")["Representative"])
result = data["Grouped_Fruit"].value_counts().reset_index()
result.columns = ["Fruit", "Occurs"]

print(result)

方案二:高频候选优先匹配法

适合唯一字符串数量极大(如10万+)的场景,通过优先处理高频字符串,避免全量距离矩阵计算,内存占用更低。

步骤与代码

import pandas as pd
from rapidfuzz import process, fuzz

# 加载数据
data = pd.DataFrame(data=["Apple", "Apple", "apple", "appel", "aple", "Orange", "Banana"], columns=["Fruits"], dtype="str")

# 1. 按频次降序排列字符串,优先处理高频项
freq_sorted = data["Fruits"].value_counts().sort_values(ascending=False)
fruit_to_group = {}
group_reps = []

# 2. 遍历高频字符串,为每个字符串匹配已有组或新建组
for fruit in freq_sorted.index:
    if fruit in fruit_to_group:
        continue
    # 查找是否有相似度≥90%的已存在组代表
    match = process.extractOne(fruit, group_reps, scorer=fuzz.ratio, score_cutoff=90)
    if match:
        fruit_to_group[fruit] = match[0]
    else:
        group_reps.append(fruit)
        fruit_to_group[fruit] = fruit

# 3. 映射并统计结果
data["Grouped_Fruit"] = data["Fruits"].map(fruit_to_group)
result = data["Grouped_Fruit"].value_counts().reset_index()
result.columns = ["Fruit", "Occurs"]

print(result)

关键优化点

  1. 先处理唯一值:40万行数据中重复字符串占比通常很高,先提取唯一值可将计算量降低几个数量级。
  2. 大小写统一:如果大小写差异不影响分组,可先执行data["Fruits"] = data["Fruits"].str.lower(),减少无效匹配。
  3. 调整相似度阈值:若90%阈值不符合需求,可修改score_cutoff(方案二)或eps参数(方案一,eps=1-阈值/100)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 01:45:03