如何在Python中对DataFrame相邻行零件编号执行Sequence Matcher匹配并提取系列?
解决方案
方案可行性说明
你的方案完全可行,必须先将零件编号转为字符串类型——因为difflib.SequenceMatcher仅处理字符串,Excel导入的列如果是数值型(比如纯数字编号)会导致匹配错误。
具体实现流程
1. 数据预处理:转换为字符串
先确保零件编号列是字符串格式:
import pandas as pd # 假设已从Excel导入DataFrame为df df['MANUFACTURER PART NUMBER 1'] = df['MANUFACTURER PART NUMBER 1'].astype(str)
2. 计算相邻行相似度并添加分数列
利用pandas.shift()获取下一行的编号,结合difflib.SequenceMatcher.ratio()计算相似度,最后一行留空:
from difflib import SequenceMatcher def get_similarity(current, next_part): if pd.isna(next_part): return None return SequenceMatcher(None, current, next_part).ratio() # 生成下一行编号列 df['next_part'] = df['MANUFACTURER PART NUMBER 1'].shift(-1) # 计算相似度分数 df['Similarity Score'] = df.apply(lambda row: get_similarity(row['MANUFACTURER PART NUMBER 1'], row['next_part']), axis=1) # 删除临时列 df.drop('next_part', axis=1, inplace=True)
3. 从高相似度编号提取零件系列
步骤3.1:将高相似度编号分组
设定相似度阈值(比如0.8,可根据实际调整),把相邻且相似度达标的编号归为同一组:
similarity_threshold = 0.8 # 当相似度低于阈值时,组ID递增,实现分组 df['group_id'] = (df['Similarity Score'] < similarity_threshold).cumsum()
步骤3.2:提取每组的公共零件系列
针对每组编号,提取最频繁的公共字符序列,或结合前缀/后缀生成带可变标记的系列名(如RK73H2ATTDxxxxF):
from collections import Counter def extract_common_series(part_numbers): # 收集所有两两编号的长公共子串(长度≥3) common_substrings = [] min_len = min(len(p) for p in part_numbers) if min_len < 3: return part_numbers[0] for i in range(len(part_numbers)): for j in range(i+1, len(part_numbers)): matcher = SequenceMatcher(None, part_numbers[i], part_numbers[j]) longest_match = matcher.find_longest_match(0, len(part_numbers[i]), 0, len(part_numbers[j])) if longest_match.size >= 3: common_substrings.append(part_numbers[i][longest_match.a:longest_match.a+longest_match.size]) if not common_substrings: return part_numbers[0] # 取出现最频繁的公共子串 most_freq_sub = Counter(common_substrings).most_common(1)[0][0] # 提取公共前缀和后缀,中间用xxxx替代可变部分 prefix = "" for idx in range(min_len): chars = [p[idx] for p in part_numbers] if len(set(chars)) == 1: prefix += chars[0] else: break suffix = "" for idx in range(1, min_len+1): chars = [p[-idx] for p in part_numbers] if len(set(chars)) == 1: suffix = chars[0] + suffix else: break if prefix or suffix: return f"{prefix}xxxx{suffix}" else: return most_freq_sub # 为每行添加对应的零件系列 df['Part Series'] = df.groupby('group_id')['MANUFACTURER PART NUMBER 1'].transform(lambda x: extract_common_series(x.tolist()))
优化建议
- 相似度阈值可根据编号的实际差异调整(比如精密零件编号相似度阈值设为0.9,通用零件设为0.7)
- 如果编号有固定格式(如前缀+数字序列+后缀),可以用正则表达式直接提取固定部分,效率比两两匹配更高
- 若数据量极大,可考虑用向量化操作替代
apply提升速度
内容的提问来源于stack exchange,提问作者Jace
相关产品推荐
相关产品推荐

