用loc条件更新必须同时指定行和列,如df.loc[df['a']>5, 'b'] = 99;多列更新需用列表如['b','c'];注意nan在布尔索引中的陷阱及掩码缓存提升性能。

用 loc 做条件更新时,必须同时指定行和列,不能只写条件
很多人写 df.loc[df['A'] > 5] = 10 想把满足条件的整行设为 10,结果报错或行为异常——loc 赋值必须明确目标列,否则 Pandas 不知道你想改哪一列。
正确做法是:在 loc 左侧明确写出列名。比如想把列 'B' 中对应 'A' > 5 的位置改为 99:
df.loc[df['A'] > 5, 'B'] = 99
- 左边
df.loc[...]是定位器,右边是赋值内容 -
df['A'] > 5返回布尔 Series,用于筛选行;'B'是目标列名(字符串)或列名列表(如['B', 'C']) - 如果目标列不存在,Pandas 会自动创建该列(dtype 取决于赋值内容)
更新多列时,列名必须用列表,不能用字符串拼接
想同时更新 'B' 和 'C' 两列?别写 'B,C' 或 'B C',这会被当成一个列名,导致 KeyError。
正确写法是传入列表:
df.loc[df['A'] == 'x', ['B', 'C']] = [100, 200]
- 右侧值可以是标量(如
0),此时所有匹配行的这两列都设为 0 - 右侧也可以是长度为 2 的可迭代对象(如列表、元组),按列顺序一一赋值
- 若右侧是 DataFrame 或二维结构,需确保 shape 匹配,否则触发广播警告或错误
用 loc 更新含 NaN 的列时,注意布尔索引的陷阱
df['A'] == 'x' 对 NaN 值返回 False,但 df['A'].isin(['x']) 同样跳过 NaN;真正危险的是 df['A'] != 'x'——它对 NaN 也返回 False,不是 True,所以不会选中缺失行。
需要显式包含 NaN 时,得用 isna() 或 isnull() 单独处理:
mask = (df['A'] == 'x') | df['A'].isna() df.loc[mask, 'B'] = -1
- 直接用
==/!=比较永远无法命中NaN -
query()同样受此影响,df.query("A == 'x'")会自动过滤掉NaN - 如果原始列是 category 类型且含未定义类别,
==可能返回NaN,进一步干扰掩码
性能敏感场景下,避免重复计算布尔掩码
如果同一条件要用于多次更新(比如先改 'B',再改 'C'),不要反复写 df['A'] > 5——每次调用都会重新生成布尔数组,小数据不明显,大数据可能拖慢 2–3 倍。
建议先存成变量:
mask = df['A'] > 5 df.loc[mask, 'B'] = 10 df.loc[mask, 'C'] = 'updated'
- 尤其当条件涉及
str.contains()、dt.month == 3等开销较大的操作时,缓存掩码很关键 - 注意:
mask是视图引用,修改df不会影响已计算好的mask,它是静态快照 - 如果后续又修改了
df['A'],这个mask就不再适用,得重算
NaN,或者以为“写一次条件就能复用”却忘了掩码是即时计算的。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











