
本文介绍如何利用 Pandas 的 str.replace() 配合正则表达式,精准移除每行字符串中末尾最后一个连字符(-)及其右侧所有字符,而保留中间的连字符不变。
本文介绍如何利用 pandas 的 `str.replace()` 配合正则表达式,精准移除每行字符串中**末尾最后一个连字符(`-`)及其右侧所有字符**,而保留中间的连字符不变。
在数据清洗过程中,常遇到类似 FUHV2-DEN 或 FUHV2-FOO-DEN 这类含多个连字符的 ID 字段,业务需求往往只需截断最后出现的 - 及其后缀(如版本号、环境标识等),而非简单按首次或全部分隔符切分。此时,使用 str.split('-').str[:-1].str.join('-') 虽直观,但存在明显缺陷:它会错误地将 FUHV2-FOO-DEN 处理为 FUHV2-FOO(正确),却也将 FUH07V2NUM(无连字符)变为空字符串(因 split('-') 返回 [FUH07V2NUM],[:-1] 取空前缀 → [],join 后为空),导致数据丢失。
更稳健、语义清晰的方案是使用正则表达式替换:
df['out'] = df['ID'].str.replace(r'-[^-]*$', '', regex=True)
✅ 正则解析:
- - :匹配字面量连字符;
- [^-]* :匹配零个或多个非连字符(确保只捕获最后一段后缀);
- $ :锚定到字符串末尾;
- 整体 r'-[^-]*$' 表示“位于行尾的、以 - 开头且后续不含 - 的后缀”,完美对应“最后一个连字符及其后全部内容”。
? 效果验证(基于原始数据): | Name1 | ID | ID_SPLIT | ID_SPLIT2 | out | |--------|---------------|----------|-----------|------------| | FUH-V2 | FUH07V2NUM | — | — | FUH07V2NUM | | FUH-V2 | FUHV2-DEN | FUHV2 | FUHV2 | FUHV2 | | FUH-V2 | FUH30V2NUM | — | — | FUH30V2NUM | | FUH-V2 | FUHV2-FOO-DEN | — | — | FUHV2-FOO |
? 注意事项:
- 必须显式指定 regex=True(Pandas 2.0+ 默认启用,但显式声明可提升可读性与兼容性);
- 正则中的 [^-] 是关键,避免误删中间连字符(如 A-B-C → A-B,而非 A);
- 若字段可能含空值(NaN),str.replace() 默认跳过,无需额外 fillna();
- 如需原地修改列,可直接赋值给 df['ID']:
df['ID'] = df['ID'].str.replace(r'-[^-]*$', '', regex=True)
该方法简洁、高效、可读性强,是处理“末尾连字符截断”类任务的标准实践。











