You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas loc按条件赋值str.extract提取结果异常及报错问题

问题原因
  • 核心错误是对pandas.Series.str.extract()的返回值理解有误:默认参数下,无论正则里写多少个捕获组,str.extract()返回的都是DataFrame类型,哪怕只有1个捕获组,得到的也是单列DataFrame,而非一维Series。
  • 当你用loc选中部分行、给单列col2赋值时,pandas期望接收一维的可迭代对象(Series/数组/列表),传入二维DataFrame会触发两类异常:
    • 若目标列是数值类型,pandas会尝试按列名、索引做对齐:你传入的全量DataFrame列名是默认的0,和目标列名col2不匹配,选中行匹配不到有效值,全部被填充为NaN。
    • 若目标列是字符串类型,pandas会直接检测到赋值类型不兼容,直接抛出ValueError: Incompatible indexer with DataFrame错误。
正确实现方案

推荐两种无副作用的写法,都能得到预期结果:

写法1:开启expand=False参数(最简洁)

给str.extract传入expand=False,提取单捕获组时会直接返回Series类型,从根源上避免类型不匹配问题,结合fillna保留非匹配行的原有值:

import pandas as pd

d = {'col1': ['62', '4 < s', '5<77', '< 10 '], 'col2': [3, 4, None, 9]}
df = pd.DataFrame(data=d)

# 提取匹配值,非匹配位置用原col2的值填充
df['col2'] = df['col1'].str.extract(r'<\s*(\d+)', expand=False).fillna(df['col2'])

如果偏好loc的显式筛选写法,可以这么写,索引自动对齐不会出错:

mask = df['col1'].str.contains(r'<\s*\d+')
df.loc[mask, 'col2'] = df.loc[mask, 'col1'].str.extract(r'<\s*(\d+)', expand=False)

写法2:手动取DataFrame的列转Series

如果忘了expand=False参数,也可以手动取出str.extract返回的单列DataFrame的第0列,得到Series后再赋值:

# 全量赋值版本
df['col2'] = df['col1'].str.extract(r'<\s*(\d+)')[0].fillna(df['col2'])

# loc版本
mask = df['col1'].str.contains(r'<\s*\d+')
df.loc[mask, 'col2'] = df.loc[mask, 'col1'].str.extract(r'<\s*(\d+)')[0]

两种写法运行后得到的结果完全一致:

col1 col2
0      62    3
1  4 < s    4
2   5<77   77
3  < 10    10

内容的提问来源于stack exchange,提问作者butterflyeffect

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 01:15:35