Pandas:缺失值处理

张开发
2026/5/24 12:13:36 15 分钟阅读
Pandas:缺失值处理
在数据分析中最常见的问题往往不是“如何计算”而是“数据是否完整”。现实中的表格数据几乎总会出现缺失值有的字段尚未录入有的记录采集失败有的内容本身就不适用。缺失值Missing Value如果处理不当轻则影响统计结果重则直接导致分析结论失真。Pandas 为缺失值提供了较完整的识别、删除、填充与插值机制这也是它在表格数据处理中非常重要的一组基础能力。一、什么是缺失值在 Pandas 中缺失值并不只是一种单一对象而是会根据数据类型以不同形式出现。对数值数据最常见的缺失标记是 NaN对日期时间类数据常见的缺失标记是 NaT在较新的可空数据类型体系中还会看到 pd.NA。Pandas 用户指南将这些表示形式统一纳入“缺失数据”的处理范畴。从 Python 语言层面看None 也常被用来表示“没有值”。None 与 NaN 都可能进入 Pandas 的缺失值处理框架但二者的来源不同、语义不同、底层类型也不同• None 是 Python 内置的空对象更强调“没有对象”• NaN 原本是 IEEE 754 浮点标准中的特殊值在 Pandas 和 NumPy 中常被用作数值缺失的表示在普通 Python 算术中None 往往会引发类型错误而 NaN 更常见的表现是“参与运算但结果仍为缺失”。例如a Noneb 10# print(a b)# TypeError: unsupported operand type(s) for : NoneType and int而对于 NaNx float(nan)print(x 10) # nanprint(x * 2) # nan因此理解缺失值时应把握两层含义1Pandas 会把多种“空值表现”纳入统一的缺失值处理框架2缺失值不只是技术现象它通常反映着数据采集、业务流程或字段语义上的问题。为了说明各种操作先建立一张学生成绩表import pandas as pdimport numpy as np scores pd.DataFrame( { 姓名: [张三, 李四, 王五, 赵六, 孙七], 班级: [一班, 一班, 二班, 二班, 一班], 数学: [95, 88, np.nan, 76, 90], 英语: [91, np.nan, 85, 79, 92], 语文: [89, 94, 87, np.nan, 88], }) print(scores)输出姓名 班级 数学 英语 语文0 张三 一班 95.0 91.0 89.01 李四 一班 88.0 NaN 94.02 王五 二班 NaN 85.0 87.03 赵六 二班 76.0 79.0 NaN4 孙七 一班 90.0 92.0 88.0二、识别缺失值缺失值处理的第一步不是删除或填充而是先识别哪些位置缺失。在 Pandas 中判断缺失值时最常见的方法有四个• isna()• isnull()• notna()• notnull()其中isna() 与 isnull() 功能相同都用于判断某个位置是否为缺失值notna() 与 notnull() 功能相同都用于判断某个位置是否为非缺失值。从当前 Pandas 文档表述来看isnull() 是 isna() 的别名notnull() 是 notna() 的别名。也就是说它们不是不同机制而只是两套常见命名。1、检查缺失位置使用 isna()print(scores.isna())输出姓名 班级 数学 英语 语文0 False False False False False1 False False False True False2 False False True False False3 False False False False True4 False False False False False其中• True 表示该位置缺失• False 表示该位置非缺失这一步非常关键。因为在实际分析中很多问题并不是“有没有缺失值”而是“缺失值集中在哪些列、哪些行、哪些字段组合中”。2、检查非缺失位置使用 notna()print(scores.notna())notna() 与 isna() 相反• True 表示有值• False 表示缺失在需要保留有效值位置、构造条件或做逻辑判断时notna() 同样非常有用。3、统计每列缺失值数量比如使用 sum() 统计print(scores.isna().sum())输出姓名 0班级 0数学 1英语 1语文 1dtype: int64这里的逻辑是isna() 先把缺失值转成 True。在 Pandas 中布尔值可参与求和True 按 1 计算因此按列求和后得到的就是每列缺失值的数量。4、统计每行缺失值数量使用 sum() 按 axis1 轴统计print(scores.isna().sum(axis1))输出0 01 12 13 14 0dtype: int64这表示第 0 行没有缺失值第 1、2、3 行各有一个缺失值第 4 行没有缺失值。如果需要把这一结果加入原表可以写成scores[缺失值数量] scores.isna().sum(axis1)print(scores)这种写法很适合在正式清洗前做“问题诊断”。三、删除缺失值识别出缺失值后最直接的处理方式是删除。Pandas 中删除缺失值的常用方法是 dropna()。dropna() 可以按行或按列删除缺失数据并支持 how、thresh、subset 等参数控制删除标准。1、删除包含缺失值的行使用 dropna()clean_scores scores.dropna()print(clean_scores)默认情况下dropna() 按行删除只要某行存在缺失值该行即被移除。这种方法简单直接但也最“激进”。如果数据量较小或缺失并不严重直接删除可能会损失过多信息。2、删除全为空值的行或列在某些场景中我们不想“一有缺失就删除”而是只删除“整行全空”或“整列全空”的情况。这时可以使用 howallscores scores.dropna(howall)如果要删除全为空值的列可以加上 axis1scores scores.dropna(axis1, howall)其中• axis0 或默认值按行处理• axis1按列处理3、只删除某些关键列存在缺失的行在真实分析中并不是所有列都同等重要。例如在成绩分析里也许“姓名”和“班级”缺失不可接受但某一门课缺失可以暂时保留。此时可以用 subset 限定判断范围scores scores.dropna(subset[姓名, 班级])这表示只检查“姓名”和“班级”两列。若这两列中存在缺失则删除该行其他列是否缺失则不影响这一删除判断。4、按“至少保留多少非缺失值”删除如果希望更灵活地按“有效值数量”来决定是否删除可以使用 thresh 参数。thresh 表示保留该行或该列所需的最少非缺失值个数。例如删除非缺失值数量不足 2 的行scores scores.dropna(thresh2)如果只针对成绩列判断scores scores.dropna(thresh2, subset[数学, 英语, 语文])这表示只统计三门成绩中的非缺失值若一行中有效成绩少于 2则删除该行。这种写法比简单的“有缺失就删”更贴近真实数据清洗需求。四、填充缺失值很多时候数据不能轻易丢弃此时更常见的做法是填充缺失值。Pandas 中最常用的方法是 fillna()。fillna() 可以使用标量、字典、Series 等对象来填充缺失位置。1、固定值填充最简单的方式是统一填入某个固定值。例如将缺失成绩都填为 0scores_zero scores.fillna(0)print(scores_zero)这种写法适合演示语法但在真实分析中应谨慎使用因为“缺失成绩”并不等于“0 分”。2、按列填充fillna() 支持用字典为不同列指定不同的填充值。对 DataFrame 而言字典键通常对应列名。例如scores_fill_dict scores.fillna( { 数学: 80, 英语: 85, 语文: 88 }) print(scores_fill_dict)这种方式比统一填 0 更灵活因为可以针对不同字段分别处理。很多时候并不是整张表都需要填充而只是某些数值列需要处理。例如scores[[数学, 英语, 语文]] scores[[数学, 英语, 语文]].fillna(0)这种写法的好处是不会影响文本列更明确地表达“只处理成绩列”。在包含字符串、类别字段或日期字段的混合表格中这种局部处理方式尤其重要。3、统计量填充在数值分析中更常见的做法是用均值、中位数等统计量填充。1用均值填充scores_mean scores.fillna(scores.mean(numeric_onlyTrue))print(scores_mean)这里 numeric_onlyTrue 表示只对数值列求均值。由于文本列无法计算均值因此这里只对数值列求均值再按列名对齐填回原表。2用中位数填充scores_median scores.fillna(scores.median(numeric_onlyTrue))print(scores_median)均值和中位数的选择取决于数据分布• 若数据分布较对称均值填充较常见• 若数据存在异常值中位数往往更稳健4、前向填充与后向填充在表格数据尤其是时间顺序数据中还有一类非常常见的填充方式不是使用固定值或统计量而是使用相邻记录中的有效值。1前向填充前向填充 ffill()用前一个有效值填补当前缺失值。scores_ffill scores.ffill()print(scores_ffill)例如李四的英语缺失会用上一行张三的英语成绩填充。如此类推。这类方法特别适合• 时间序列• 按时间或顺序记录的日志• 数据本身具有“上一状态延续到下一状态”的含义需要注意如果第一行本身就是缺失值前向填充无法处理该位置因为它上面没有有效值。2后向填充后向填充 bfill()用后一个有效值填补当前缺失值。scores_bfill scores.bfill()print(scores_bfill)它与前向填充方向相反更适合“后续记录可反推当前状态”的场景。3只对指定列进行前向或后向填充scores[[数学, 英语, 语文]] scores[[数学, 英语, 语文]].ffill()对于包含文本列的表格这种写法通常更安全。ffill() 与 bfill() 可以分别看作 fillna(methodffill) 与 fillna(methodbfill) 的便捷写法。在混合类型表格中缺失值填充通常应优先按列进行而不宜直接对整表统一处理。五、插值填充如果缺失值出现在连续数值数据中仅靠固定值或相邻值填充并不总是合理。此时可以使用 interpolate() 进行插值。interpolate() 用于按照某种插值规则填充缺失值默认方法是 linear。插值方法只有在数据具有顺序、数值间距或时间间距意义时才合理。1、线性插值例如某列数据按顺序呈现变化趋势ser pd.Series([80, np.nan, 84, np.nan, 88])print(ser.interpolate())输出0 80.01 82.02 84.03 86.04 88.0dtype: float64默认线性插值会根据相邻有效值估计中间缺失值。线性插值适合• 连续数值型数据• 含有顺序关系的数据• 希望保留变化趋势而不是简单复制前后值的场景插值并不是一般意义上的“万能补空”它依赖数据在索引或顺序上的连续关系。2、基于时间或索引插值Pandas 文档还列出多种插值方法例如 time、index、values 等。它们的适用前提是索引本身具有数值或时间意义。例如在时间序列中ts pd.Series( [80, np.nan, 88], indexpd.to_datetime([2026-03-01, 2026-03-02, 2026-03-04])) print(ts.interpolate(methodtime))输出2026-03-01 80.0000002026-03-02 82.6666672026-03-04 88.000000dtype: float64这种方式会考虑索引间隔而不仅仅是位置顺序。因此在真正的时间序列分析中它往往比简单线性插值更合理。3、关于 MultiIndex 的限制对于带有 MultiIndex 的 Series 或 DataFrame只有 methodlinear 得到支持。这意味着在多级索引场景下插值方法的选择会受到限制需要额外注意。六、将特殊值规范为缺失值在现实数据中缺失值并不一定一开始就以 NaN 形式出现。很多数据源会用某些特殊值表示“无数据”例如• -1• 999• • N/A对固定特殊编码常用 replace() 转换为缺失值对满足条件的一批值则常用 mask() 进行替换。例如把所有小于 0 的成绩先视为异常再替换为缺失值num_cols [数学, 英语, 语文]scores[num_cols] scores[num_cols].mask(scores[num_cols] 0, np.nan)或者使用 replace() 把某个特殊编码替换为缺失值scores scores.replace(-1, np.nan)这类步骤通常应放在正式缺失值处理之前。也就是说真实流程往往是先把“伪缺失值”规范成真正的缺失值再统一使用 dropna()、fillna()、interpolate() 等方法处理。七、按条件处理缺失值Pandas 的缺失值处理并不总是“一刀切”。很多时候我们需要按条件、按列、按组来分别处理。1、只处理数值列num_cols [数学, 英语, 语文]scores[num_cols] scores[num_cols].fillna(scores[num_cols].mean())这比直接对整表调用 fillna() 更安全因为它避免了文本列参与不合适的数值处理。2、先筛选再处理例如只对某个班级的数据进行填充mask scores[班级] 一班scores.loc[mask, [数学, 英语, 语文]] ( scores.loc[mask, [数学, 英语, 语文]] .fillna(0))这种做法适合“不同群体采用不同规则”的场景。3、按组填充在实际分析中经常需要“按组求平均后填充本组缺失值”。例如按班级平均分填充该班缺失成绩scores[数学] scores[数学].fillna( scores.groupby(班级)[数学].transform(mean))这里的思路是先按班级分组计算每组数学平均值再把对应组的平均值用于填充该组缺失位置。这类方法通常比“整列统一均值填充”更贴近现实因为它保留了组内差异。八、缺失值处理中的常见误区1、误以为“缺失值一定要删掉”实际上删除只是其中一种选择。在很多业务场景下直接删除会丢失重要样本尤其在样本量本来就不大时更应谨慎。2、误以为“填充 0 最简单也最合理”填 0 只是技术上最容易但语义上可能完全不合理。例如考试成绩缺失不一定代表 0 分传感器读数缺失也不等于真实值为 0。3、忽视顺序结构对于时间数据或按顺序记录的数据直接用整列均值填充可能比前向填充、后向填充或时间插值更不合理。数据是否有顺序性是选择缺失值处理策略时的重要依据。4、没有先统一“伪缺失值”很多原始数据中的 -1、空字符串、NA 等如果不先规范成缺失值就可能在后续统计中被当作正常数据参与计算。5、只记方法不管业务含义缺失值处理的根本误区在于将其理解为纯粹的语法问题而忽略其业务语义。实际上处理策略应始终围绕“这个缺失究竟意味着什么”来决定。 小结在 Pandas 中缺失值处理并不是机械地“删或填”而是先识别缺失再结合字段类型、数据顺序与业务语义选择合适策略。isna()、dropna()、fillna()、interpolate() 等方法共同构成了一套较完整的缺失数据处理机制。“点赞有美意赞赏是鼓励”

更多文章