
本文介绍如何利用 Pandas 的 str.replace() 配合正则表达式,精准删除每行字符串中最后一个连字符(-)及其右侧所有字符,而保留前面的连字符(如存在多个),适用于清洗含多级标识符的 ID 字段。
本文介绍如何利用 pandas 的 `str.replace()` 配合正则表达式,精准删除每行字符串中**最后一个连字符(`-`)及其右侧所有字符**,而保留前面的连字符(如存在多个),适用于清洗含多级标识符的 id 字段。
在数据处理中,常遇到类似 FUHV2-FOO-DEN 或 FUHV2-DEN 这样的 ID 字符串,需统一截断至最后一个 - 之前的部分(即提取主标识符),但又不能误删中间的 -(如 FUH-V2 中的 - 必须保留)。此时,使用 str.split('-').str[:-1].str.join('-') 虽直观,却存在隐患:它会错误地将不含 - 的字符串(如 FUH07V2NUM)转为空字符串或引发索引异常,且对多连字符场景逻辑不稳健。
更可靠、简洁且符合语义的方案是使用正则表达式替换:
df['out'] = df['ID'].str.replace(r'-[^-]*$', '', regex=True)
✅ 正则解析:
- - :匹配字面量连字符;
- [^-]* :匹配零个或多个非连字符(即直到行尾前最后一个 - 后的所有内容);
- $ :锚定到字符串末尾,确保只作用于最后一个连字符及其后缀;
- 整体 r'-[^-]*$' 精准定位“末尾的 - + 其后无 - 的任意字符”,并将其替换为空字符串。
? 效果示例:
| Name1 | ID | out |
|--------|---------------|-----------|
| FUH-V2 | FUH07V2NUM | FUH07V2NUM ← 无 -,原样保留
| FUH-V2 | FUHV2-DEN | FUHV2 ← 移除 -DEN
| FUH-V2 | FUH30V2NUM | FUH30V2NUM ← 无 -,原样保留
| FUH-V2 | FUHV2-FOO-DEN | FUHV2-FOO ← 仅移除末尾 -DEN,保留中间 -
⚠️ 注意事项:
- 务必设置 regex=True(Pandas 1.0+ 默认为 True,但显式声明更安全);
- 若字段含缺失值(NaN),str.replace() 会自动保持 NaN,无需额外处理;
- 如需原地修改列,可直接赋值给原列名:df['ID'] = df['ID'].str.replace(...);
- 测试正则建议使用 regex101.com 实时验证边界逻辑。
该方法兼具性能、可读性与鲁棒性,是 Pandas 字符串清洗中的推荐实践。











