如何在Python中区分混合单元格中的产品编码与数量
如何在Python中区分混合单元格中的产品编码与数量
看起来你遇到的核心问题是列位置的语义偶尔失效,再加上5位数量和产品编码的数字重叠,导致了误判。结合你的Excel结构(左右分栏的表格、物种标题分区),我们可以从几个维度优化逻辑,让识别更精准:
1. 优先利用列的语义定位,避免“一刀切”判断
你当前的代码里,不管是产品编码列还是数量列,只要是5位数字就判定为产品编码,这很容易把数量列里的5位数字误认。其实表格的列本身就有明确的语义:产品编码列(左表的第3列、右表的第8列)本来就该放编码,数量列(左表第4列、右表第9列)本来就该放数量,我们应该优先尊重这个位置逻辑:
修改判断函数与列处理逻辑
def is_product_code(value): # 只针对产品编码列的判断:必须是整数(或可转整数的浮点数),且为5位 if pd.isna(value): return False # 处理12345.0这类浮点数情况 try: int_val = int(value) except (ValueError, TypeError): return False return len(str(int_val)) == 5 # 处理左表时的逻辑调整 if current_species_left and left_col: # 产品编码列:只判断当前列是否符合编码规则 product_code = row[2] if not pd.isna(row[2]) and is_product_code(row[2]) else None # 数量列:直接取值,不再用编码规则排除(哪怕是5位数字,也优先按数量处理) quantity = row[3] if not pd.isna(row[3]) else None value = row[4] if not pd.isna(row[4]) else None # 后续添加到data_rows的逻辑不变...
这样就不会把数量列里的5位数字误判成产品编码了——毕竟数量列的本职就是记录数量,哪怕数值刚好是5位,也优先按数量处理。
2. 处理“同一单元格混合编码与数量”的场景
如果某些单元格里同时存在编码和数量(比如内容是12345 100或12345,50.5),我们可以用正则表达式来拆分内容:匹配5位数字作为编码,剩下的部分提取为数量。
新增拆分辅助函数
import re def split_mixed_cell(cell_value): if pd.isna(cell_value): return (None, None) cell_str = str(cell_value).strip() # 匹配独立的5位数字(避免和更长数字混淆) code_match = re.search(r'\b\d{5}\b', cell_str) product_code = int(code_match.group()) if code_match else None # 提取数量:移除编码后,匹配整数或小数 quantity_str = re.sub(r'\b\d{5}\b', '', cell_str).strip().replace(',', '') try: quantity = float(quantity_str) if '.' in quantity_str else int(quantity_str) except ValueError: quantity = None return (product_code, quantity)
在列处理中加入混合内容判断
比如处理左表行时:
if current_species_left and left_col: cell_code = row[2] cell_qty = row[3] prod_code = None qty = None # 先处理产品编码列的混合情况 if not pd.isna(cell_code): if len(str(cell_code).strip().split()) >= 2: # 单元格混合了编码和数量,拆分 code_from_code_col, qty_from_code_col = split_mixed_cell(cell_code) prod_code = code_from_code_col # 如果数量列是空的,用拆分出的数量 if pd.isna(cell_qty): qty = qty_from_code_col else: # 正常情况,按编码规则判断 prod_code = cell_code if is_product_code(cell_code) else None # 再处理数量列的混合情况 if not pd.isna(cell_qty): if len(str(cell_qty).strip().split()) >= 2: # 数量列混合了编码和数量,拆分 code_from_qty_col, qty_from_qty_col = split_mixed_cell(cell_qty) qty = qty_from_qty_col # 如果编码列是空的,用拆分出的编码 if prod_code is None: prod_code = code_from_qty_col else: qty = cell_qty value = row[4] if not pd.isna(row[4]) else None # 正常添加到data_rows...
3. 补充业务规则(如果有)
如果你们的产品编码有固定范围(比如都是10000-50000之间的数字),可以把这个规则加入判断函数,进一步过滤误判:
def is_product_code(value): if pd.isna(value): return False try: int_val = int(value) except (ValueError, TypeError): return False # 新增:产品编码必须在指定范围内 return len(str(int_val)) == 5 and 10000 <= int_val <= 50000
4. 容错标记:人工核查存疑行
如果还是有无法确定的情况,可以在结果中新增Flag字段标记存疑,方便后续人工核对:
# 在添加到data_rows时加入标记 flag = "正常" if prod_code is not None and qty is not None: try: if len(str(int(qty))) == 5: flag = "存疑:编码与数量均为5位" except (ValueError, TypeError): pass data_rows.append({ "Species": current_species_left, "Product Code": prod_code, "Product": left_col, "Quantity": qty, "Value": value, "Company Name": company_info["Company Name"], "Mailing Address": company_info["Mailing Address"], "Plant Name": company_info["Plant Name"], "Plant Address": company_info["Plant Address"], "Source Sheet": sheet, "Flag": flag # 新增标记字段 })
按照这些思路修改你的代码,应该能大幅提升识别的准确性啦!
备注:内容来源于stack exchange,提问作者JonathonV92
相关产品推荐
相关产品推荐

