如何在Python的Pandas中提取字符串的匹配与非匹配词汇?
解决Pandas列内字符串相似度对比,提取匹配与差异项的方案
核心思路
先将相邻的相似字符串归为一组,计算每组的共同词汇作为匹配项,再通过每行词汇与共同词汇的差集得到差异项。
步骤1:定义工具函数
先实现字符串拆分、相似度计算的基础函数:
import pandas as pd # 将字符串拆分为词汇集合 def get_word_set(s): return set(s.split()) # 计算两个字符串的Jaccard相似度(衡量词汇重叠程度) def jaccard_similarity(s1, s2): set1 = get_word_set(s1) set2 = get_word_set(s2) intersection = len(set1 & set2) union = len(set1 | set2) return intersection / union if union != 0 else 0
步骤2:对相似行分组
遍历数据,根据相邻行的相似度阈值(这里设为0.5,可调整)将连续相似的行归为一组:
# 示例数据 data = {'产品描述': ['Red HMS Carabiner', 'Blue HMS Carabiner', 'HMS Carabiner Orange', 'Liquid Chalk - 100ml', 'Liquid Chalk - 100ml (Case of 10)']} df = pd.DataFrame(data) # 初始化分组列表 groups = [] current_group = [0] for i in range(1, len(df)): sim_score = jaccard_similarity(df['产品描述'].iloc[i-1], df['产品描述'].iloc[i]) # 相似度高于阈值则加入当前组,否则新建组 if sim_score >= 0.5: current_group.append(i) else: groups.append(current_group) current_group = [i] groups.append(current_group)
步骤3:提取匹配项与差异项
对每个分组计算共同词汇,再生成每行的差异内容:
# 初始化结果列 df['匹配项'] = df['产品描述'] df['差异项'] = pd.NA for group in groups: # 获取组内所有行的词汇集合 word_sets = [get_word_set(df['产品描述'].iloc[idx]) for idx in group] # 计算组内所有词汇的交集(共同词汇) common_words = set.intersection(*word_sets) # 按原字符串的词汇顺序整理共同词汇,避免乱序 first_row_str = df['产品描述'].iloc[group[0]] common_str = ' '.join([word for word in first_row_str.split() if word in common_words]) # 遍历组内每行,计算差异项 for idx in group: current_word_set = get_word_set(df['产品描述'].iloc[idx]) diff_words = current_word_set - common_words # 按原字符串顺序整理差异项 diff_str = ' '.join([word for word in df['产品描述'].iloc[idx].split() if word in diff_words]) df['匹配项'].iloc[idx] = common_str df['差异项'].iloc[idx] = diff_str if diff_str else pd.NA
步骤4:整理输出结果
将匹配项替换原产品描述列,得到目标格式:
# 调整列顺序并输出 df_final = df.rename(columns={'匹配项': '产品描述'})[['产品描述', '差异项']] print(df_final)
运行后输出结果:
产品描述 差异项 0 HMS Carabiner Red 1 HMS Carabiner Blue 2 HMS Carabiner Orange 3 Liquid Chalk - 100ml <NA> 4 Liquid Chalk - 100ml (Case of 10)
优化提示
- 相似度阈值:如果你的数据中相似字符串的词汇重叠度更高,可以调高阈值(比如0.7);反之调低。
- 词汇拆分逻辑:如果字符串包含特殊符号(比如连字符、斜杠),可以用正则表达式优化拆分,例如
re.findall(r'\b\w+\b|\([^)]+\)', s),能完整保留括号内的内容。 - 非连续相似行:如果相似行不连续,可以考虑用聚类算法(比如K-Means)基于字符串特征分组,但连续相似场景下用相邻相似度分组效率更高。
内容的提问来源于stack exchange,提问作者hydroproxy
相关产品推荐
相关产品推荐

