str.extract()提取单个匹配组需正则含捕获组,返回首匹配或NaN;str.extractall()返回全部匹配的MultiIndex DataFrame;str.contains()查任意位置,str.match()仅查开头。

用 str.extract() 提取单个匹配组
最常用也最直接的方式是 str.extract(),它要求正则表达式中至少有一个捕获组(即用圆括号 () 包裹的部分),否则会报错 ValueError: No groups to match。
比如从一列邮箱中提取用户名:
df['username'] = df['email'].str.extract(r'^(.+)@')
注意点:
-
^和$在str.extract()中不是必需的,因为默认只找第一个匹配;加了反而可能因边界限制漏匹配 - 如果某行没匹配上,结果为
NaN,不是空字符串 - 只返回第一个匹配项,即使字符串里有多个符合模式的子串
用 str.extractall() 拿到全部匹配结果
当一行里可能有多个目标片段(比如日志里多次出现 IP 地址),str.extract() 就不够用了,得换 str.extractall()。
立即学习“Python免费学习笔记(深入)”;
它返回一个 MultiIndex 的 DataFrame,索引包含原始行号和匹配序号:
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
ips = df['log'].str.extractall(r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b')
常见陷阱:
- 结果不是和原
df行数对齐的,不能直接赋值给新列;需用.unstack()或按需聚合 - 正则必须含捕获组,和
extract()一样 - 性能比
extract()低不少,大数据量时留意
str.contains() 和 str.match() 别混用
这两个都返回布尔值,但行为完全不同:
-
str.contains(r'error', case=False):只要字符串任意位置含error就返回True -
str.match(r'ERROR.*'):等价于re.match(),只检查**开头是否匹配**,不加^也没用
典型误用:想筛选所有含数字的行,写了 df[df['text'].str.match(r'\d+')] —— 这只会选中「开头就是数字」的行。正确写法是 str.contains(r'\d')。
性能与编码细节不能忽略
正则在 Pandas 里是逐元素调用 Python 的 re 模块,本身不快。如果列很长,又频繁调用,容易卡住。
几个实际建议:
- 提前编译正则:用
re.compile(r'pattern')然后传给str.extract(pat=compiled_pattern),避免重复编译 - 确保字符串列是
string类型(Pandas 1.0+ 推荐),而不是object,否则str方法可能隐式转类型,出错或变慢 - 遇到中文、emoji 等 Unicode 字符,正则里别漏
flags=re.U(不过 Pandas 默认已启用 Unicode 模式,多数情况不用显式加)
真正麻烦的是嵌套括号、非贪婪匹配和多行文本——这些地方正则稍有不慎就逻辑错位,而 Pandas 不报语法错误,只默默返回空或意外结果。

















