loc配合布尔索引是修改DataFrame某几行某几列的首选方式,可避免SettingWithCopyWarning;np.where适合单列条件替换;复杂逻辑推荐assign而非多个loc或apply。

用 loc 配合布尔索引是最直接、最安全的方式
直接改原 DataFrame 的某几行某几列,loc 是首选。它明确指定“哪些行 + 哪些列”,不会触发 SettingWithCopyWarning,也避免链式赋值失效。
常见错误是写成 df[df['A'] > 5]['B'] = 0——这实际操作的是视图副本,原数据不变,且可能静默失败。
- 正确写法:
df.loc[df['A'] > 5, 'B'] = 0 - 支持多条件:
df.loc[(df['A'] > 5) & (df['C'] == 'X'), ['B', 'D']] = [100, 'new'](注意括号和&,不能用and) - 若目标列不存在,
loc会自动创建(但通常应提前确保列已存在)
numpy.where 适合单列条件替换,语义清晰、性能好
当只需要根据一个条件对一列做“满足则 A,否则 B”式替换时,np.where 比嵌套 loc 更简洁,且底层向量化,速度更快。
例如把所有负数替换成 0,正数保留原值:df['score'] = np.where(df['score'] 。
- 支持嵌套:
np.where(df['status'] == 'A', 'active', np.where(df['status'] == 'I', 'inactive', 'unknown')) - 注意:第二个参数(True 分支)和第三个参数(False 分支)长度必须一致,或可广播;传入标量没问题
- 不推荐用它批量改多列——每列得单独调一次,代码冗余
用 mask 或 where 替换满足条件的值(而非整行整列)
当想“把符合条件的位置设为 NaN 或某个固定值”,mask 比 loc 更自然;反过来,where 是保留符合条件的值、其余设为 NaN。
比如清洗异常值:把所有大于 999 的销售额设为 NaN:df['sales'] = df['sales'].mask(df['sales'] > 999)。
-
mask(cond, other=NaN):cond 为 True 的位置,替换为other -
where(cond, other=NaN):cond 为 True 的位置保留原值,否则用other - 二者都支持
inplace=True,但返回值仍是 Series/DataFrame,建议显式赋值更可控 - 注意:它们默认只作用于调用对象本身,不修改原 DataFrame 的其他列
批量修改多列时,别硬写多个 loc,用字典 + apply 或 assign 更可维护
如果逻辑复杂(比如按地区、时间、等级组合判断,然后同时更新价格、状态、标签三列),硬拆成三个 loc 赋值不仅重复,还容易漏条件同步。
这时可以封装逻辑到函数,再用 apply 行级处理,或用 assign 构造新列:
- 用
apply:df[['price', 'status', 'tag']] = df.apply(lambda r: calc_new_vals(r), axis=1, result_type='expand') - 用
assign(推荐):df = df.assign(price=lambda d: np.where(d['level']=='VIP', d['price']*0.9, d['price']), status=lambda d: np.where(d['score']>80, 'OK', 'NG')) - 注意:
apply行级操作在大数据量下明显变慢;assign内部仍走向量化,优先选它
真正容易被忽略的是条件表达式的求值顺序和空值处理——比如 df['col'] > 5 在含 NaN 时结果是 False,不是 NaN,可能导致本该跳过的行被误改。需要明确用 df['col'].fillna(0) > 5 或 df['col'].gt(5, fill_value=0) 控制 NaN 行为。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











