str.extract()提取首个匹配组,返回单列dataframe,需正则含捕获组;str.extractall()返回多级索引dataframe获取全部匹配;str.contains()仅返回布尔值,不可用于提取。

用 str.extract() 提取第一个匹配组
这是最常用也最安全的提取方式,适用于每行最多只需要一个匹配结果的场景。它返回一个 DataFrame(单组)或 DataFrame(多组),缺失匹配则填充 NaN。
常见错误是直接对非字符串列调用 str.extract(),会报 AttributeError: Can only use .str accessor with string values;务必先确认列类型为 object 且内容实际为字符串,必要时加 .astype(str)。
示例:从邮箱列中提取用户名部分
df['username'] = df['email'].str.extract(r'^([^@]+)@')
注意点:
- 正则必须带括号捕获组,否则返回空
DataFrame - 默认只取第一个匹配,即使文本中有多个邮箱也只提最前面那个
- 如果想提取所有匹配,得换
str.findall(),不是extract()
用 str.extractall() 拿到全部匹配及其位置
当一行里可能有多个符合规则的子串(比如日志里多次出现 IP 地址),且你还关心它们在原文中的顺序和行索引时,str.extractall() 是唯一选择。它返回一个带多级索引的 DataFrame,第一级是原行号,第二级是匹配序号。
容易踩的坑:
- 结果不是和原
df行数对齐的,不能直接赋值给新列(会报长度不匹配) - 若某行无匹配,该行完全不出现在结果里——不是填
NaN,是彻底消失 - 正则里仍需捕获组,但可含多个组,例如
r'(d{1,3}.d{1,3}.d{1,3}.d{1,3}):(d+)'同时提 IP 和端口
典型用法是配合 unstack() 或 groupby() 做后续聚合,比如统计每行出现了几次手机号。
别乱用 str.contains() 当提取工具
str.contains() 只返回布尔值,不是提取函数。有人误以为加 regex=True 就能“抽出来”,其实它连字符串都不返回,只是告诉你“有没有”。拿它赋值给新列,得到的是一堆 True/False,不是你想要的数据。
正确分工:
- 筛选行用
df[df['col'].str.contains(r'pattern')] - 提取内容用
str.extract()或str.extractall() -
str.match()仅检查是否从头匹配,也不提取
性能上,contains() 比 extract() 快,因为它不用构造新字符串,但功能完全不同,不能混用。
正则写错导致空结果?先检查这三处
提取结果全是 NaN 是高频问题,通常不是 Pandas 的锅,而是正则本身没命中。优先排查:
- 原始数据含首尾空格或换行符:
df['col'].str.strip().str.extract(...)更稳妥 - 大小写敏感:默认区分大小写,要忽略就加
flags=re.I参数,如.str.extract(r'error', flags=re.I) - 特殊字符没转义:比如想匹配路径中的反斜杠
,得写成r'\folder'或'\\folder';点号.要匹配字面量就得写.
调试技巧:先用 df['col'].head().apply(lambda x: re.search(r'your_pattern', str(x))) 在小样本上验证正则逻辑,比直接跑全量更省时间。
真正麻烦的是嵌套结构或上下文依赖的提取,比如“取冒号后、分号前的内容”,这时候正则容易写崩,不如先用 str.split() 或 str.partition() 分段处理,比硬刚复杂正则更可靠。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











