str.extract()提取首个匹配捕获组并返回dataframe,未匹配行填nan;str.extractall()提取全部匹配项并返回multiindex dataframe;二者均需括号定义捕获组,且须注意空值处理与正则标志传参。

用 str.extract() 提取第一个匹配组
直接调用 str.extract() 是最常用的方式,它会返回一个 DataFrame(即使只有一列),每行对应原 Series 中第一个符合正则的捕获组。注意:没匹配上的行会变成 NaN。
- 必须用圆括号
()明确写出捕获组,否则返回空 DataFrame - 正则里写
(\d+)能提取数字,但写\d+(没括号)结果全为空 - 如果想提取多个字段,比如「城市-编号」中的两部分,写成
(\w+)-(\d+),结果是两列 -
expand=False参数无效 —— 这个参数在str.extractall()里才有作用
示例:df['text'].str.extract(r'ID:(\w+)') 从 "ID:abc123" 中抽取出 "abc123"
用 str.extractall() 拿到全部匹配项
当一行文本含多个匹配时,str.extract() 只取第一个,而 str.extractall() 返回 MultiIndex DataFrame,索引包含原行号和匹配序号,适合做聚合或展开处理。
- 返回结构天然带层级索引,直接
.reset_index()才方便后续 join 或 merge - 若某行无匹配,该行不会出现在结果中(不像
extract()填NaN) - 配合
groupby(level=0)可以把同一行的多个提取结果聚合成 list 或拼接字符串 - 性能比
extract()低,别在大表上盲目替换
示例:df['log'].str.extractall(r'error=(\w+)') 从含多个 error=xxx 的日志行中捞出全部 error 值
避免 str.match() 和 str.contains() 的误用
这两个方法不返回子串,只返回布尔值或匹配对象,常被新手误当成提取工具。
-
str.match(r'\d+') → bool:只判断是否「从头开始」匹配,不是提取 -
str.contains(r'\d+') → bool:只是标记「是否存在」,不能拿内容 -
str.findall(r'\d+')返回 list,虽能拿到全部匹配,但类型是 object,后续要apply(lambda x: x[0] if x else None)才能转成标量,不如直接用extract() - 想用
re.search()手动遍历?没必要 —— Pandas 已封装好,且向量化更快
正则标志和空值处理的坑
str.extract() 默认不支持 re.IGNORECASE 这类标志,得显式传入 flags 参数;另外空值(None 或 NaN)会直接报错或跳过,不自动过滤。
- 大小写忽略写成
df['name'].str.extract(r'(mr|ms|dr)', flags=re.I) - 含 NaN 列调用前建议先用
df['col'].fillna('').str.extract(...),否则可能触发ValueError: buffer source array is read-only - 提取后得到 object 类型列,数值字段记得用
astype(float)或pd.to_numeric(..., errors='coerce')转换 - 正则太宽泛(如
.*)容易吞掉不该吞的内容,建议用非贪婪.*?或明确边界锚点^/$
真正麻烦的从来不是写对正则,而是原数据里那些没预料到的空格、换行、编码异常字符 —— 提取前先 sample(5).tolist() 看一眼真实值,比反复改正则快得多
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











