pandas 缺失值处理实战指南:isna/notna 过滤、dropna 删除与 ffill/fillna 填充
【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas
导读
缺失数据是任何数据分析任务都无法回避的现实问题。本指南以 pandas 官方「与其他工具(R / SAS / Stata / SPSS)对比」文档中缺失数据部分为核心骨架,系统讲解 pandas 处理缺失值的四类核心操作:用isna/notna构建布尔掩码过滤行、用dropna删除缺失行、用ffill沿前向填充缺失值、用fillna以指定值(如列均值)填充。读完本文,你将掌握一套可复制、可直接落地的缺失值清洗方案,并能从源码层面理解这些方法的参数语义与底层行为。
缺失数据的表示与传播语义
在 pandas 中,缺失数据使用特殊的浮点值NaN(Not a Number)表示。doc/source/getting_started/comparison/includes/missing_intro.rst明确了其两条关键语义:
- 缺失值会在数值运算中传播:
NaN参与加减乘除等运算时,结果仍为NaN; - 聚合计算默认忽略缺失值:例如
sum()、mean()等聚合操作在默认情况下会跳过NaN,不会报错。
例如对合并后的outer_join(其定义见下文)执行运算:
outer_join["value_x"] + outer_join["value_y"] # 任一列为 NaN 时结果为 NaN outer_join["value_x"].sum() # 默认跳过缺失值,返回非 NaN 的合计这一点与 SAS、Stata 等统计工具在概念上一致——它们同样拥有各自的缺失值哨兵。但 pandas 有一个关键差异:缺失值不能与它的哨兵值直接比较。在 SAS 中可以写if value_x = .来筛选缺失行,在 Stata 中可以写list if value_x == .,而 pandas 中outer_join["value_x"] == np.nan永远是False(因为NaN != NaN)。这正是 pandas 必须提供isna/notna这类专用方法的原因。
用 isna / notna 布尔掩码过滤缺失行
pandas 提供Series.isna和Series.notna(以及等价的isnull/notnull别名)来判断每个元素是否缺失,返回与序列等长的布尔掩码。doc/source/getting_started/comparison/includes/missing.rst给出了最典型的用法——结合布尔索引过滤 DataFrame 的行:
# 筛选出 value_x 列为缺失的行 outer_join[outer_join["value_x"].isna()] # 筛选出 value_x 列不为缺失的行(反向过滤) outer_join[outer_join["value_x"].notna()]其原理是:isna()逐元素返回布尔 Series,而 DataFrame 的[]索引器接收布尔 Series 时会保留掩码为True的所有行,从而完成行级过滤。两个方法在 DataFrame 实现 与 Series 实现 中均有同名方法,底层最终落到 pandas._libs 中缺失值判定逻辑,对NaN、None、NaT(时间缺失)等各类缺失哨兵统一识别。
使用建议
- 需要保留缺失行做进一步排查时用
isna(); - 需要剔除缺失行参与后续计算时,
notna()掩码即可直接用于索引,无需再写~取反; - 与
value_x == np.nan这类错误写法相比,isna()是唯一可靠的正规途径。
dropna:直接删除包含缺失值的行
如果目标是快速清理数据,DataFrame.dropna()是最直接的方法。沿用上文示例:
# 删除任何含缺失值的行 outer_join.dropna()默认行为是删除任何包含至少一个缺失值的行。从 DataFrame.dropna 源码签名 可以看到完整参数:
| 参数 | 默认值 | 作用 |
|---|---|---|
axis | 0(行方向) | 指定沿行(0/index)还是沿列(1/columns)删除缺失值 |
how | "any" | "any"表示该行/列存在任一缺失即删除;"all"表示全部缺失才删除 |
thresh | 无 | 要求该行/列至少保留的非缺失值数量达到该阈值才保留(与how二选一) |
subset | None | 仅在指定的列/行子集内检查缺失,其余位置忽略 |
inplace | False | 是否原地修改(不推荐,建议使用返回值) |
ignore_index | False | 删除行后是否重置索引为连续整数 |
实际使用示例:
# 只有当一行全部为缺失时才删除 outer_join.dropna(how="all") # 只针对 value_x、value_y 两列检查缺失 outer_join.dropna(subset=["value_x", "value_y"]) # 保留至少含 3 个非缺失值的行 outer_join.dropna(thresh=3) # 删除全为空值的列 outer_join.dropna(axis="columns", how="all")dropna的 docstring 明确指向用户指南中的 缺失数据专题文档,那里列出了 pandas 究竟把哪些值视为缺失(NaN、None、NaT等),以及更多工作方式。
ffill:沿前向填充缺失值
时间序列或有序数据中,缺失值常采用「用前一个有效值填充」的策略,即前向填充(forward fill):
# 用前一行的值填充当前缺失值 outer_join.ffill()ffill是fillna(method="ffill")的便捷别名,语义是:对每个缺失位置,取同一列中最近的上一个非缺失值进行填充。若某缺失值之前没有任何有效值(如序列开头的NaN),该位置会保持缺失。pandas 同时提供反向版本bfill()(backward fill),用后一个有效值填充。
前向填充非常适合处理传感器读数、股价、日志等按时间顺序排列的数据——缺失往往意味着「数据未变化」或「上一时刻的值仍然有效」。需要说明的是,ffill的填充方向是沿axis展开的,默认沿行方向(即逐列向下填充),也可通过axis参数调整为按行水平填充。
fillna:用指定值替换缺失
当缺失值有明确的业务替代方案时,Series.fillna()/DataFrame.fillna()可接受标量、字典、Series 或 DataFrame 进行填充。missing.rst给出的经典场景是用该列的均值填充:
# 用 value_x 列的均值替换该列中的缺失值 outer_join["value_x"].fillna(outer_join["value_x"].mean())注意这里利用了前文提到的聚合语义——mean()默认忽略NaN,因此计算出的均值本身不受缺失值影响,填入后能保持列分布的整体水平。fillna还支持更多用法:
# 用固定标量填充整列 outer_join["value_x"].fillna(0) # 不同列用不同值(传入字典) outer_join.fillna({"value_x": 0, "value_y": outer_join["value_y"].mean()}) # 仅填充数值列,并使用其各自的均值 outer_join.fillna(outer_join.mean(numeric_only=True))与dropna的「删除信息」策略相比,fillna属于「保留行、补全信息」的策略,在样本量宝贵或需要保持行对齐时更为适用。除了均值,中位数median()、众数mode()、常数 0 或业务默认值都是常见的填充选择,具体取决于列的数据分布与分析目标。
在工具对比语境中的定位
本指南所讲解的内容来自 pandas 官方「Getting started → Comparison」系列文档,具体被 与 SAS 的对比、与 Stata 的对比 以及 与 SPSS 的对比 三处通过.. include:: includes/missing.rst复用。这些页面围绕同一份合并演示数据展开,其中outer_join由 merge 示例 通过df1.merge(df2, on=["key"], how="outer")生成,因为外连接必然产生一侧缺失的匹配行,从而自然构成缺失值演示场景。
也就是说,上述四类操作正是 pandas 给 SAS/Stata/SPSS 老用户的「缺失值处理翻译对照表」:
| 统计工具习惯 | pandas 对应操作 |
|---|---|
用哨兵值= ./== .比较筛选缺失 | isna()/notna()布尔掩码 |
| 数据步中显式删除缺失观测 | dropna() |
| 用上一个观测值前向结转 | ffill() |
| 用指定值(如均值)替换缺失 | fillna(value) |
进阶:更完整的缺失值处理工具箱
missing.rst在示例后明确指引读者:pandas 提供 多种缺失数据处理方法。除本文四类操作外,该专题文档还涵盖:
- 缺失值插值
interpolate():按线性、多项式、时间等方式对缺失点插值,适用于平滑趋势数据; - 缺失值标记
isna()的聚合应用:如统计每列缺失比例df.isna().mean(),用于数据质量评估; - 缺失值与其他缺失表示:如
NaT(时间戳缺失)、pd.NA(可为空数据类型下的统一缺失标量)的识别与转换; fillna的时间感知填充:method="ffill"配合时间索引可精确实现「按时间前向填充」。
结合源码路径可继续深入:DataFrame.dropna、Series.isna、Series.notna 均为各系列方法族的入口,后续可沿其调用链追踪缺失值判定的底层实现。
小结:缺失值处理的决策路径
面对缺失数据,可按以下路径选择策略:
- 先体检:用
isna().sum()/isna().mean()摸清缺失分布,判断缺失集中在哪些列、占比多少; - 再决策:缺失占比低且行样本宝贵 →
dropna();有序数据存在「延续」语义 →ffill()/bfill();缺失有合理替代(均值、中位数、0)→fillna();趋势型数据 →interpolate(); - 最后验证:填充或删除后,用
notna().all()确认数据已无缺失,再进入下游建模或分析。
记住核心原则:永远不要用== np.nan判断缺失,统一走isna/notna体系;dropna与fillna的取舍本质是「删信息」与「补信息」之间的业务权衡。
【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考