Python 中 str.contains() 处理括号字符串的正确用法

pandas 的 `str.contains()` 默认启用正则表达式模式,而圆括号 `()` 是正则元字符,直接匹配含括号的字符串会报错或失败;解决方法是禁用正则(`regex=false`)或对特殊字符进行转义。

在使用 Pandas 进行文本筛选与替换时,str.contains() 是一个高频方法。但许多开发者初次遇到包含括号、点号、星号等正则特殊字符的字符串时,会发现匹配“失效”——例如以下代码:

import pandas as pd

df = pd.DataFrame([['Table 1 (not in use after 1 Apr 2025)'], 
                    ['wefwfe'], 
                    ['eqv']], 
                   columns=['Venue'])

# ❌ 错误:默认 regex=True,( ) 被解释为正则分组,导致语法错误或无匹配
df.loc[df['Venue'].str.contains('Table 1 (not in use after 1 Apr 2025)'), 'Venue'] = 'Table'

运行时可能抛出 re.error: missing ) 等异常,或静默返回空结果——这是因为 str.contains() 默认将输入字符串当作正则表达式解析,而未转义的 ( 和 ) 在正则中需成对出现并具有分组语义。

✅ 正确做法有两种:

方案一:显式关闭正则(推荐用于纯文本匹配)
设置 regex=False,此时字符串按字面量(literal)精确匹配,无需转义:

df.loc[df['Venue'].str.contains('1 (not in use after 1 Apr 2025)', regex=False),

'Venue'] = 'Table'

方案二:使用原始字符串 + 手动转义
若需保留正则能力(如模糊匹配),应对元字符添加反斜杠,并推荐使用原始字符串(r'')避免 Python 字符串转义干扰:

df.loc[df['Venue'].str.contains(r'1 \(not in use after 1 Apr 2025\)', regex=True), 'Venue'] = 'Table'

⚠️ 注意事项:

  • regex=False 性能更优,且语义清晰,只要不需要正则功能,应优先选用
  • 若字符串含多个正则元字符(如 ., *, +, ?, [, ] 等),regex=False 可彻底规避转义复杂性;
  • 避免混用 loc 链式赋值(如 .loc[...].values = ...),应统一使用 df.loc[condition, col] = value 写法,确保操作安全;
  • 对空值(NaN)敏感:str.contains() 默认跳过 NaN,如需控制可传入 na=False(返回 False)或 na=True(返回 True)。

最终输出符合预期:

    Venue
0   Table
1  wefwfe
2     eqv

掌握 regex 参数的含义与取舍,是写出健壮、可维护字符串处理逻辑的关键一步。