np.where适合两层条件判断,嵌套易出错;np.select更适合三岔及以上分支,结构清晰;loc分步赋值更可控;避免使用apply做列间条件判断。

用 numpy.where 做两层条件判断最直接
当只有两个分支(比如“大于100 → A,否则 → B”),np.where 是最轻量的选择。它支持嵌套,但三层以上就容易写错括号和逗号位置。
常见错误是把 pandas Series 当成布尔数组直接参与逻辑运算,结果报 ValueError: The truth value of a Series is ambiguous——这是因为 Python 不知道该对整个 Series 判真还是逐元素判。
- 必须用
&(不是and)、|(不是or)、~(不是not)做元素级逻辑运算 - 每个条件要用括号包住,比如
(df['age'] > 25) & (df['city'] == 'Beijing') - 嵌套写法示例:
np.where((df['score'] >= 90), 'A', np.where(df['score'] >= 80, 'B', 'C'))
numpy.select 更适合三岔及以上分支
一旦条件超过两个,np.where 嵌套可读性急剧下降。np.select 是专为多重条件设计的,结构清晰、易维护。
它要求你显式定义条件列表和对应取值列表,最后还能指定默认值(default 参数)。漏写 default 且某行不满足任何条件时,会填入 np.nan,这点常被忽略。
立即学习“Python免费学习笔记(深入)”;
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 条件必须是布尔型 Series 或数组,同样要用
&/|连接 - 条件顺序重要:从上到下匹配第一个为
True的分支,后续不再检查 - 示例:
np.select([df['x'] 10], ['low', 'mid', 'high'], default='unknown')
用 pandas.DataFrame.loc 分步赋值更可控
当逻辑复杂、涉及多列计算或需要调试中间状态时,分步用 loc 赋值反而最稳妥。它不像向量化函数那样“一气呵成”,但每一步都可打印验证。
容易踩的坑是忘记初始化目标列,或者重复使用 loc 时条件覆盖不全,导致部分值残留旧数据或变成 NaN。
- 先创建空列:
df['grade'] = ''或df['grade'] = np.nan - 再按优先级顺序写条件:
df.loc[df['score'] >= 90, 'grade'] = 'A',接着df.loc[(df['score'] >= 80) & (df['score'] - 最后补默认:
df.loc[df['grade'] == '', 'grade'] = 'F'(注意字符串空值判断要写== '',不能用.isna())
别用 apply + 自定义函数处理大批量数据
虽然 df.apply(lambda x: ...) 写起来像 Python 原生 if-else,看着顺手,但它在大表(>10 万行)上性能极差——因为是逐行解释执行,无法利用底层 NumPy 向量化加速。
除非你的条件依赖跨行逻辑(比如“当前行 score 大于前一行 score”),否则纯列间条件判断一律避开 apply。
- 如果非得用函数封装逻辑,至少用
np.vectorize包一层,但效果仍不如原生select或where - 调试时临时用
apply没问题,上线前务必替换掉 - 错误示范:
df['result'] = df.apply(lambda r: 'X' if r['a'] > 5 and r['b']
多重条件赋值真正的难点不在语法,而在于条件之间的互斥性和覆盖完整性。建议先用 value_counts() 检查各分支结果分布,再人工抽样几行,对照原始条件逐条验算——比盯着代码找括号位置管用得多。

















