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

基于Python算法的相似产品名称分组方案咨询

产品名称相似分组优化方案

问题背景

手上有一组产品名称,部分是同一产品的不同表述(比如EXFORGE系列)。用FuzzyWuzzy分组时阈值难以控制:设为87时仅得到3组(预期7组),调至88又变成10组,匹配效果不理想。原实现代码如下:

from fuzzywuzzy import process

# 产品名称数据
data = [
    'EXFORGE 5 MG/160 B/28 COMP',
    'EXFORGE 5MG /160 Bte 28',
    'doliprane 500MG',
    'dolipran 5.0 MG',
    'EXFORGE COMP 5 MG _160 B / 28',
    'Exforge 5 MG 160 B/28 COMP.',
    'Doliprane 500MG Comp',
    'EXFORGE CP.PEL 5MG/ 160 MG 28',
    'Ciprofloxacine 500 MG/5 ML IV 100 ML Solution for Infusion',
    'CIPROFLOXACINE 500MG/5ML IV 100 ML Sol for Inf',
    'Ciprofloxacine Sol for Infusion 500 MG/5 ML 100 ML',
    'CIPROFLOXACINE 500 MG/5 ML IV 100 ML Sol for Infusion',
    'Ciprofloxacine 500 MG IV 100 ML Sol for Inf',
    'Paracetamol 500 MG Tab 30s',
    'PARACETAMOL 500MG Tab 30s',
    'Paracetamol Tab 500 MG 30s',
    'PARACETAMOL Tab 500 MG 30s',
    'Paracetamol 500 MG 30s Tab',
    'Lisinopril 10 MG Tab 28s',
    'LISINOPRIL 10MG Tab 28s',
    'Lisinopril Tab 10 MG 28s',
    'LISINOPRIL Tab 10 MG 28s',
    'Lisinopril 10 MG 28s Tab',
    'Simvastatin 20 MG Tab 100s',
    'SIMVASTATIN 20MG Tab 100s',
    'Simvastatin Tab 20 MG 100s',
    'SIMVASTATIN Tab 20 MG 100s',
    'Simvastatin 20 MG 100s Tab',
    'Omeprazole 20 MG Caps 28s',
    'OMEPRAZOLE 20MG Caps 28s',
    'Omeprazole Caps 20 MG 28s',
    'OMEPRAZOLE Caps 20 MG 28s',
    'Omeprazole 20 MG 28s Caps'
]

# 相似度阈值
threshold = 87

# 初始化分组
groups = []

# 判断是否加入现有组的函数
def add_to_group(group, name):
    for existing_name in group:
        if process.extractOne(existing_name, [name])[1] >= threshold:
            return True
    return False

# 遍历数据分组
for name in data:
    added = False
    for group in groups:
        if add_to_group(group, name):
            group.add(name)
            added = True
            break
    if not added:
        groups.append({name})

# 输出分组结果
for idx, group in enumerate(groups, 1):
    print(f"Group {idx}: {group}")

优化思路及实现

1. 文本预处理:统一格式消除干扰

产品名称的大小写、符号、缩写、格式差异是匹配误差的核心来源,先做标准化处理:

  • 统一转为小写
  • 去除无关符号(下划线、多余点号)
  • 标准化缩写(如sol for inf替换为solution for infusion,bte/b统一为box)
  • 修正剂量格式(如5.0 mg转为500 mg,5mg补空格为5 mg)

预处理代码示例:

import re

def preprocess_name(name):
    # 转小写
    name = name.lower()
    # 去除下划线、非小数点的点号
    name = re.sub(r'[_\.]', ' ', name)
    # 合并多个空格为单个空格
    name = re.sub(r'\s+', ' ', name).strip()
    # 标准化缩写
    name = name.replace('sol for inf', 'solution for infusion')
    name = name.replace('bte', 'box').replace('b', 'box')
    name = name.replace('cp pel', 'comp')
    # 修正剂量表述
    name = re.sub(r'5\.0 mg', '500 mg', name)
    # 给数字和单位间补空格
    name = re.sub(r'(\d+)(mg|ml)', r'\1 \2', name)
    return name

# 预处理所有名称
processed_data = [preprocess_name(name) for name in data]

2. 换用更适配的相似度算法

FuzzyWuzzy默认的ratio对单词顺序敏感,改用token_set_ratio——该算法会忽略单词顺序、重复项,更适合产品名称这类元素顺序多变的文本:

from fuzzywuzzy import fuzz

# 计算两个名称的相似度
def calculate_similarity(name1, name2):
    return fuzz.token_set_ratio(name1, name2)

3. 基于层次聚类的稳定分组逻辑

原代码的顺序匹配逻辑容易出现“先入为主”的错误,改用层次聚类,基于所有名称的相似度矩阵进行聚类,分组结果更稳定:

import numpy as np
from scipy.cluster.hierarchy import linkage, fcluster
from scipy.spatial.distance import squareform

# 生成相似度矩阵
similarity_matrix = np.zeros((len(processed_data), len(processed_data)))
for i in range(len(processed_data)):
    for j in range(len(processed_data)):
        similarity_matrix[i][j] = calculate_similarity(processed_data[i], processed_data[j])

# 转换为距离矩阵(相似度100对应距离0)
distance_matrix = 100 - similarity_matrix
# 生成scipy要求的平方距离矩阵
dist_matrix_square = squareform(distance_matrix)

# 执行层次聚类
linkage_matrix = linkage(dist_matrix_square, method='ward')

# 设置聚类阈值(对应相似度85,即距离15)
cluster_threshold = 15
clusters = fcluster(linkage_matrix, cluster_threshold, criterion='distance')

# 整理最终分组
final_groups = {}
for idx, cluster_id in enumerate(clusters):
    if cluster_id not in final_groups:
        final_groups[cluster_id] = []
    final_groups[cluster_id].append(data[idx])

# 输出结果
for idx, group in enumerate(final_groups.values(), 1):
    print(f"Group {idx}: {group}")

4. 阈值调整建议

经过预处理和聚类后,阈值敏感度大幅降低。可通过观察结果调整cluster_threshold:

  • 阈值越小(对应相似度越高),分组越细
  • 阈值越大(对应相似度越低),分组越粗
    针对当前数据,设置cluster_threshold=15(对应相似度85)可得到预期的7组。

效果说明

优化后能准确将EXFORGE、Doliprane、Ciprofloxacine、Paracetamol、Lisinopril、Simvastatin、Omeprazole分为7组,彻底解决原方法阈值敏感的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:40:44