Python中基于多列条件为DataFrame提取符合格式序列号填充新列
实现方案
核心规则对齐
首先明确目标列Serial Number Final的硬校验标准:
- 字符串总长度固定为17位
- 必须包含
MP标识,且MP固定位于字符串第3-4位(下标2、3,从0开始计数),整体匹配XXMPXXXXXXXXXXXXX格式(前2位任意字符,MP后接13位任意字符,总长度17)
现有3个候选列可作为序列号提取源:Serial Number New、Serial Number + Keyword、Serial Number Old,已知数据存在三类问题:值为0、序列号带冗余前后缀、序列号前缀缺失。
处理逻辑
以MP为固定锚点做提取清洗,按列优先级逐行校验,直到拿到符合规则的序列号:
- 优先遍历准确率最高的候选列(可根据实际数据调整顺序,默认按给出的列名顺序)
- 对每个单元格值先做无效值过滤:剔除空值、数值0、字符串'0'、无MP标识的内容
- 定位MP在字符串中的位置,向前截取最多2位作为前缀,向后截取最多13位作为后缀,拼接后校验长度和MP位置,符合要求则作为最终值
- 当前列提取失败则自动取下一个候选列做清洗,所有列都提取失败的行标记为空,后续可人工校验
可直接运行的代码
import pandas as pd import numpy as np def extract_valid_serial(cell_val): # 过滤基础无效值 if pd.isna(cell_val) or cell_val == 0: return None val_str = str(cell_val).strip() if val_str in ('', '0', 'None', 'nan'): return None # 定位MP锚点 mp_pos = val_str.find('MP') if mp_pos == -1: return None # 按锚点截取前后片段,凑齐17位长度 prefix = val_str[max(0, mp_pos - 2) : mp_pos] suffix_need_len = 17 - len(prefix) - 2 suffix = val_str[mp_pos+2 : mp_pos+2 + suffix_need_len] serial_candidate = prefix + 'MP' + suffix # 最终规则校验 if len(serial_candidate) == 17 and serial_candidate[2:4] == 'MP': return serial_candidate return None # 按优先级配置候选列,准确率高的列放前面 candidate_columns = [ 'Serial Number New', 'Serial Number + Keyword', 'Serial Number Old' ] # 逐列填充目标列 df['Serial Number Final'] = pd.NA for col in candidate_columns: empty_mask = df['Serial Number Final'].isna() df.loc[empty_mask, 'Serial Number Final'] = df.loc[empty_mask, col].apply(extract_valid_serial) # 可选:提取所有清洗失败的行做人工核查 error_rows = df[df['Serial Number Final'].isna()]
适配说明
- 如果实际数据中
Serial Number Old列准确率更高,直接调整candidate_columns里的列顺序即可 - 若存在后缀缺失的场景,可以在拼接逻辑里补对应长度的占位符,默认逻辑会过滤长度不足的无效值
- 冗余前后缀不需要提前枚举规则,锚点匹配逻辑会自动剔除MP前后超出长度的无关字符
内容的提问来源于stack exchange,提问作者Khalil Basir
相关产品推荐
相关产品推荐

