应使用 loc + 条件判断或 np.where 进行条件性填充,而非 fillna();多条件需用括号和 & 连接;apply 适用于分段或查表等复杂逻辑。

用 loc + 条件判断做条件性填充,别用 fillna() 直接套
直接对整列调用 fillna() 无法区分“该不该填”,它只会无差别补全。真正要按另一列阈值决定是否填充,必须先定位满足条件的行,再赋值。比如:当 score grade 的空值填成 "F"。
实操建议:
- 用
df.loc[df['score'] 筛出“低分且 grade 为空”的行索引 - 再用
df.loc[...] = "F"赋值,避免链式赋值警告 - 不要写
df[df['score'] —— 这会触发 <code>SettingWithCopyWarning,且实际不生效
numpy.where() 一行搞定带条件的空值替换
如果逻辑是“满足条件就填固定值,否则保持原值(含 NaN)”,numpy.where() 比 loc 更紧凑。它天然支持三元逻辑,且返回新数组,不依赖原 df 结构。
示例:把 income > 10000 且 category 为空的行,填为 "high":
import numpy as np
df['category'] = np.where(
(df['income'] > 10000) & df['category'].isna(),
"high",
df['category']
)
注意点:
- 多个条件必须用括号包住,再用
&连接(不是and) -
df['category'].isna()返回布尔 Series,和数值条件对齐维度 - 第三参数必须是原列(
df['category']),不能写None或省略,否则非匹配行会变NaN
用 apply() 处理复杂阈值逻辑(比如分段、查表)
当阈值不是简单大小比较,而是分段(如 score 0–59→F,60–69→D)、或需查外部映射字典时,apply() 配合自定义函数更清晰。
示例:根据 age 填充缺失的 group,规则是 0–17→"minor",18–64→"adult",65+→"senior":
def fill_group(row):
if pd.isna(row['group']) and not pd.isna(row['age']):
if row['age']
<p>关键提醒:</p>
- 一定要检查
row['group']是否为空,否则会覆盖已有值 - 也要检查
row['age']是否为空,避免TypeError: ' - 性能敏感场景慎用
apply——它本质是 Python 循环,大数据量时比向量化操作慢一个数量级
警惕 inplace=True 在条件填充中的失效陷阱
很多人以为 df.fillna(..., inplace=True) 能配合条件使用,但其实它不接受布尔索引——inplace 只作用于整列。试图写 df[df['x']>5]['y'].fillna(..., inplace=True) 不仅无效,还会报 SettingWithCopyWarning。
正确做法只有两个:
- 用
loc显式索引后赋值(推荐,语义明确) - 用
numpy.where()或mask()生成新值再赋给列(函数式风格)
真正容易被忽略的是:空值填充常和数据类型隐式转换交织。比如用字符串填 int 列,会强制转为 object 类型;后续数值计算可能意外失败。动手前先用 df.dtypes 看一眼目标列类型。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











