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

如何用Python NLP技术匹配两个DataFrame行并补全分类信息

解决品牌多分类场景下的优惠信息与产品分类匹配问题

核心思路:先缩范围再精准匹配

针对品牌存在多分类的情况,避免直接全表匹配,先通过BRAND字段缩小候选分类范围,再用提取的优惠关键词和分类文本做相似度匹配,既提升效率又减少错误匹配。

1. 预处理:构建品牌-分类映射字典

先把df1按品牌分组,将每个品牌对应的所有分类信息整理成字典,避免每次匹配都扫描全表:

import pandas as pd

# 按BRAND分组,存储每个品牌的所有分类条目
brand_category_map = df1.groupby('BRAND').apply(
    lambda x: x[['PRODUCT_CATEGORY', 'PARENT_CATEGORY', 'CATEGORY_ID']].to_dict('records')
).to_dict()

2. 模糊匹配实现(适合中小数据量)

用fuzzywuzzy的分词集匹配(token_set_ratio),能忽略关键词和分类文本的顺序差异,提升匹配准确性:

from fuzzywuzzy import fuzz

def match_best_category(row):
    brand = row['BRAND']
    keywords = row['extracted_keywords']  # 假设已提取好的关键词列表
    # 品牌无对应分类时返回空值
    if brand not in brand_category_map:
        return pd.Series([None, None, None])
    
    candidates = brand_category_map[brand]
    keyword_str = ' '.join(keywords).lower()
    best_score = 0
    best_cat = None
    
    for cat in candidates:
        # 拼接分类文本并统一小写
        cat_str = f"{cat['PRODUCT_CATEGORY']} {cat['PARENT_CATEGORY']}".lower()
        # 计算分词集匹配得分
        score = fuzz.token_set_ratio(keyword_str, cat_str)
        if score > best_score:
            best_score = score
            best_cat = cat
    
    # 设置得分阈值,低于阈值返回空(可根据业务调整)
    if best_score >= 60 and best_cat:
        return pd.Series([best_cat['PRODUCT_CATEGORY'], best_cat['PARENT_CATEGORY'], best_cat['CATEGORY_ID']])
    return pd.Series([None, None, None])

# 应用到df2
df2[['PRODUCT_CATEGORY', 'PARENT_CATEGORY', 'CATEGORY_ID']] = df2.apply(match_best_category, axis=1)

3. TF-IDF余弦相似度匹配(适合大数据量)

当数据量较大时,用TF-IDF结合余弦相似度的方法更高效,能更好处理多关键词的复杂匹配:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

# 预处理df1:拼接分类文本,按品牌构建TF-IDF模型
brand_tfidf_dict = {}
for brand, group in df1.groupby('BRAND'):
    group['cat_text'] = (group['PRODUCT_CATEGORY'] + ' ' + group['PARENT_CATEGORY']).str.lower()
    vectorizer = TfidfVectorizer(stop_words='english')  # 若为中文场景需替换为中文停用词
    tfidf_mat = vectorizer.fit_transform(group['cat_text'])
    brand_tfidf_dict[brand] = {
        'vectorizer': vectorizer,
        'tfidf_matrix': tfidf_mat,
        'cat_info': group[['PRODUCT_CATEGORY', 'PARENT_CATEGORY', 'CATEGORY_ID']].to_dict('records')
    }

def tfidf_match_category(row):
    brand = row['BRAND']
    keywords = row['extracted_keywords']
    if brand not in brand_tfidf_dict:
        return pd.Series([None, None, None])
    
    data = brand_tfidf_dict[brand]
    keyword_str = ' '.join(keywords).lower()
    # 转换关键词为TF-IDF向量
    keyword_vec = data['vectorizer'].transform([keyword_str])
    # 计算余弦相似度
    sim_scores = cosine_similarity(keyword_vec, data['tfidf_matrix'])[0]
    # 取相似度最高的分类
    max_sim_idx = sim_scores.argmax()
    max_sim = sim_scores[max_sim_idx]
    
    # 设置相似度阈值(可根据业务调整)
    if max_sim >= 0.3:
        best_cat = data['cat_info'][max_sim_idx]
        return pd.Series([best_cat['PRODUCT_CATEGORY'], best_cat['PARENT_CATEGORY'], best_cat['CATEGORY_ID']])
    return pd.Series([None, None, None])

# 应用到df2
df2[['PRODUCT_CATEGORY', 'PARENT_CATEGORY', 'CATEGORY_ID']] = df2.apply(tfidf_match_category, axis=1)

4. 优化多分类匹配的准确性

  • 业务规则优先:如果已知品牌的主品类(比如苹果的主品类是数码产品),给df1添加PRIORITY字段(数值越小优先级越高),匹配时先筛选高优先级的分类候选,再计算得分。
  • 文本清洗对齐:把df1的PRODUCT_CATEGORY和PARENT_CATEGORY也做和OFFER列一样的清洗(去掉非字母数字字符、统一大小写),减少文本差异带来的匹配误差。
  • 批量加速:大数据量下用swifter库替代原生apply,自动选择最优执行方式(向量化或并行):
import swifter
df2[['PRODUCT_CATEGORY', 'PARENT_CATEGORY', 'CATEGORY_ID']] = df2.swifter.apply(match_best_category, axis=1)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:02:19