如何比较1.0、1、1 in等同度量不同格式值并识别列组异值列
处理方案
核心思路是放弃直接做文本相似度对比,先把单元格内容统一解析为标准结构化格式,再做匹配,具体落地步骤如下:
1. 单元格内容归一化解析
对每个单元格的文本做两步处理:
- 提取数值:用正则匹配文本中的数字部分,统一转成固定精度的浮点数,比如
1、1.0都统一转为1.0 - 维度归一:预设场景内常用的单位映射规则,非数值类内容统一做大小写/空格清洗
- 长度单位映射:
in、inch统一映射为inch,mm、millimeter统一映射为mm - 文本类内容:比如颜色
Red、red统一清洗为red
- 长度单位映射:
2. 异值列判断逻辑
对同一列组的同一行所有单元格,按内容类型分别匹配:
- 数值+度量类:数值误差在预设阈值内、单位维度一致即判定为同值
- 文本类:清洗后的内容完全一致即判定为同值
- 取同一组内出现次数最多的值为基准值,和基准值不匹配的列即为待删除的异值列
参考实现代码
import re from collections import defaultdict # 可根据业务场景扩展单位映射表 UNIT_MAPPING = { 'in': 'inch', 'inch': 'inch', 'mm': 'mm', 'millimeter': 'mm' } # 数值比较允许的误差阈值,可调整 NUM_EPS = 1e-6 def parse_cell(text): text = str(text).strip().lower() # 尝试解析为数值+单位格式 num_match = re.search(r'(\d+\.?\d*)', text) if num_match: num = float(num_match.group(1)) unit_part = text.replace(num_match.group(1), '').strip() unit = UNIT_MAPPING.get(unit_part, unit_part) return ('measure', num, unit) # 非数值类直接返回清洗后的文本 return ('text', text) def find_abnormal_cols(group_cols, row_data): """ group_cols: 同组的列名列表 row_data: 对应行的{列名: 原始值}字典 返回需要删除的异值列列表 """ parse_result = {col: parse_cell(row_data[col]) for col in group_cols} # 统计每个解析结果的出现次数,取出现最多的为基准值 count = defaultdict(list) for col, res in parse_result.items(): count[res].append(col) max_count = max(len(v) for v in count.values()) benchmark = [k for k, v in count.items() if len(v) == max_count][0] # 筛选和基准值不匹配的异值列 abnormal_cols = [] for col, res in parse_result.items(): if res[0] != benchmark[0]: abnormal_cols.append(col) continue if res[0] == 'measure': if abs(res[1] - benchmark[1]) > NUM_EPS or res[2] != benchmark[2]: abnormal_cols.append(col) else: if res[1] != benchmark[1]: abnormal_cols.append(col) return abnormal_cols # 样例测试 if __name__ == '__main__': # 测试行2的ABCD组,预期返回['A'] row2_abcd = {'A':'2.1', 'B':'2', 'C':'2 in', 'D':'2 inch'} print(find_abnormal_cols(['A','B','C','D'], row2_abcd)) # 测试行0的EFGH组,预期返回['G'] row0_efgh = {'E':'Red', 'F':'Red', 'G':'Blue', 'H':'Red'} print(find_abnormal_cols(['E','F','G','H'], row0_efgh))
优化方向
如果场景内单位类型较多、需要支持跨单位换算,可引入Python的pint单位处理库,可自动识别2.54 cm和1 inch为等值,进一步提升匹配准确率。
内容的提问来源于stack exchange,提问作者Shawn Jamal
相关产品推荐
相关产品推荐

