WEBKT

Pandas 数据清洗实战 缺失值处理的终极指南

14 0 0 0

1. 缺失值是个啥?为啥要处理?

2. 缺失值的检测:火眼金睛找出来

2.1 isnull()和notnull()

2.2 info()

2.3 缺失值可视化

2.3.1 热力图

2.3.2 缺失值矩阵

3. 缺失值的处理:填补还是删除?

3.1 删除缺失值

3.1.1 dropna()方法的基本用法

3.1.2 how参数

3.1.3 thresh参数

3.1.4 删除缺失值的注意事项

3.2 填补缺失值

3.2.1 常数填补

3.2.2 前向/后向填充

3.2.3 插值填充

3.2.4 模型预测填充

3.2.5 填补缺失值的注意事项

4. 进阶技巧:处理更复杂的情况

4.1 多列缺失值处理

4.2 缺失值与异常值处理结合

4.3 复杂场景下的缺失值处理流程

5. 总结与最佳实践

6. 补充说明:一些常见问题和解答

7. 结束语

大家好,我是老码农,今天我们来聊聊数据分析中一个非常重要但也常常被忽视的环节——缺失值处理。作为一名程序员,你肯定遇到过数据不完整的情况,无论是从数据库里导出的,还是从API接口获取的,总会有那么一些数据是缺失的。如果不对这些缺失值进行处理,你的数据分析结果很可能就是错的,模型训练也无法进行。别担心,今天我就带你一起探索Pandas中处理缺失值的各种方法,让你轻松应对各种数据清洗难题。

1. 缺失值是个啥?为啥要处理?

首先,我们要搞清楚什么是缺失值。在Pandas中,缺失值通常用NaN(Not a Number,非数字)表示。还有一些情况下,缺失值可能会被表示为None或者其他占位符,比如-999。总之,缺失值就代表着某个位置的数据是空的,没有值。

为什么处理缺失值这么重要?原因有很多:

  • 影响数据分析结果: 缺失值会影响统计分析的结果,例如均值、方差等。如果直接用含有缺失值的数据进行计算,结果肯定是不准确的。
  • 导致模型训练失败: 很多机器学习算法都无法直接处理含有缺失值的数据。如果你不处理缺失值,模型就无法训练,或者训练出来的模型效果很差。
  • 破坏数据完整性: 缺失值会破坏数据的完整性,影响数据的可信度。
  • 引发错误: 在一些情况下,缺失值可能会导致程序运行时出现错误。

总之,处理缺失值是数据清洗过程中至关重要的一步。只有处理好缺失值,才能保证数据的质量,为后续的数据分析和建模打下坚实的基础。

2. 缺失值的检测:火眼金睛找出来

在开始处理缺失值之前,我们首先要做的就是检测数据中是否存在缺失值,以及缺失值的分布情况。Pandas提供了非常方便的工具来帮助我们完成这项任务。

2.1 isnull()notnull()

这两个方法是Pandas中最常用的缺失值检测方法。isnull()方法用于判断数据中的每个元素是否为缺失值,如果是缺失值,则返回True,否则返回Falsenotnull()方法则相反,用于判断数据中的每个元素是否不是缺失值,如果是缺失值,则返回False,否则返回True。这两个方法通常与sum()方法结合使用,可以统计出每列中缺失值的数量。

import pandas as pd
import numpy as np
# 创建一个包含缺失值的DataFrame
data = {
'A': [1, 2, np.nan, 4, 5],
'B': [np.nan, 2, 3, np.nan, 5],
'C': [1, 2, 3, 4, 5]
}
df = pd.DataFrame(data)
# 使用isnull()检测缺失值
print(df.isnull())
# 使用notnull()检测非缺失值
print(df.notnull())
# 统计每列缺失值的数量
print(df.isnull().sum())

输出结果:

A B C
0 False True False
1 False False False
2 True False False
3 False True False
4 False False False
A B C
0 True False True
1 True True True
2 False True True
3 True False True
4 True True True
A 1
B 2
C 0
dtype: int64

从输出结果可以看出,isnull()方法返回一个布尔值的DataFrame,表示每个元素是否为缺失值。notnull()方法则返回一个布尔值的DataFrame,表示每个元素是否不是缺失值。isnull().sum()方法则统计了每列缺失值的数量,方便我们了解缺失值的分布情况。

2.2 info()

info()方法可以提供DataFrame的整体信息,包括每列的数据类型、非缺失值的数量等。通过info()方法,我们可以快速了解数据中是否存在缺失值,以及缺失值的分布情况。

# 使用info()方法查看DataFrame的信息
df.info()

输出结果:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 A 4 non-null float64
1 B 3 non-null float64
2 C 5 non-null int64
dtypes: float64(2), int64(1)
memory usage: 248.0 bytes

从输出结果可以看出,info()方法显示了每列的非缺失值数量。例如,列'A'有4个非缺失值,列'B'有3个非缺失值,列'C'有5个非缺失值。这说明列'A'和列'B'中存在缺失值,而列'C'中没有缺失值。

2.3 缺失值可视化

除了使用上述方法进行数值统计外,我们还可以通过可视化来更直观地了解缺失值的分布情况。常用的可视化方法包括热力图和缺失值矩阵。

2.3.1 热力图

热力图可以使用颜色来表示缺失值和非缺失值,缺失值通常用不同的颜色来表示,例如白色或灰色。通过热力图,我们可以直观地看到缺失值的分布情况,例如缺失值是否集中在某些列或某些行。

import matplotlib.pyplot as plt
import seaborn as sns
# 使用热力图可视化缺失值
sns.heatmap(df.isnull(), yticklabels=False, cbar=False, cmap='viridis')
plt.show()

输出结果:

从热力图可以看出,列'A'和列'B'中存在缺失值,列'C'中没有缺失值。缺失值的位置用白色表示,非缺失值用其他颜色表示。

2.3.2 缺失值矩阵

缺失值矩阵可以使用不同的颜色或标记来表示缺失值和非缺失值,缺失值通常用空白或特定的标记来表示。通过缺失值矩阵,我们可以直观地看到缺失值的分布情况,例如缺失值是否集中在某些列或某些行,以及缺失值之间的关系。

import missingno as msno
# 使用缺失值矩阵可视化缺失值
msno.matrix(df)
plt.show()

输出结果:

从缺失值矩阵可以看出,列'A'和列'B'中存在缺失值,列'C'中没有缺失值。缺失值的位置用空白表示,非缺失值用线条表示。通过观察缺失值矩阵,我们可以更直观地了解缺失值的分布情况和缺失值之间的关系。

3. 缺失值的处理:填补还是删除?

检测到缺失值之后,我们就需要对缺失值进行处理了。处理缺失值的方法有很多,主要分为两大类:删除填补

3.1 删除缺失值

删除缺失值是最简单粗暴的方法,但是也是最容易损失数据的方法。如果缺失值数量很少,或者缺失值对分析结果的影响很小,那么删除缺失值是一个不错的选择。Pandas提供了dropna()方法来删除缺失值。

3.1.1 dropna()方法的基本用法

dropna()方法可以删除包含缺失值的行或列。可以通过axis参数指定删除行还是删除列,axis=0表示删除行,axis=1表示删除列。默认情况下,dropna()方法会删除包含任何缺失值的行。

# 删除包含缺失值的行
df_dropna_row = df.dropna()
print("删除行后:")
print(df_dropna_row)
# 删除包含缺失值的列
df_dropna_col = df.dropna(axis=1)
print("删除列后:")
print(df_dropna_col)

输出结果:

删除行后:
A B C
4 5.0 5.0 5
删除列后:
Empty DataFrame
Columns: []
Index: []

从输出结果可以看出,dropna()方法默认删除包含任何缺失值的行。如果设置axis=1,则删除包含任何缺失值的列。注意,dropna()方法会返回一个新的DataFrame,原始的DataFrame不会被修改。

3.1.2 how参数

how参数用于指定删除缺失值的策略。how='any'表示只要包含缺失值就删除,这是默认值。how='all'表示只有当所有值都为缺失值时才删除。

# 只有当所有值都为缺失值时才删除行
df_dropna_all = df.dropna(how='all')
print("how='all'后:")
print(df_dropna_all)

输出结果:

how='all'后:
A B C
0 1.0 NaN 1
1 2.0 2.0 2
2 NaN 3.0 3
3 4.0 NaN 4
4 5.0 5.0 5

从输出结果可以看出,how='all'参数不会删除任何行,因为没有哪一行所有值都为缺失值。

3.1.3 thresh参数

thresh参数用于指定删除缺失值的阈值。thresh=n表示至少有n个非缺失值才保留该行或列。例如,thresh=2表示至少有2个非缺失值才保留该行或列。

# 至少有2个非缺失值才保留该行
df_dropna_thresh = df.dropna(thresh=2)
print("thresh=2后:")
print(df_dropna_thresh)

输出结果:

thresh=2后:
A B C
0 1.0 NaN 1
1 2.0 2.0 2
2 NaN 3.0 3
3 4.0 NaN 4
4 5.0 5.0 5

从输出结果可以看出,thresh=2参数保留了所有行,因为每行至少有两个非缺失值。

3.1.4 删除缺失值的注意事项

  • 删除缺失值会损失数据,所以在使用dropna()方法时,一定要慎重考虑,评估删除缺失值对分析结果的影响。
  • 如果缺失值数量很多,或者缺失值对分析结果的影响很大,那么删除缺失值可能不是一个好的选择。
  • 在删除缺失值之前,最好先对缺失值的分布情况进行分析,了解缺失值的产生原因和规律,以便更好地选择删除策略。

3.2 填补缺失值

填补缺失值是指用某种方法将缺失值替换为非缺失值。填补缺失值可以保留更多的数据,减少信息损失。常用的填补方法包括:

3.2.1 常数填补

常数填补是指用一个固定的值来替换缺失值。这个值可以是0、平均值、中位数、众数等,也可以是自定义的值。常数填补是最简单的方法,但是也是最容易产生偏差的方法。Pandas提供了fillna()方法来实现常数填补。

# 用0填补缺失值
df_fillna_0 = df.fillna(0)
print("用0填补后:")
print(df_fillna_0)
# 用平均值填补缺失值
df_fillna_mean = df.fillna(df.mean())
print("用平均值填补后:")
print(df_fillna_mean)
# 用中位数填补缺失值
df_fillna_median = df.fillna(df.median())
print("用中位数填补后:")
print(df_fillna_median)

输出结果:

0填补后:
A B C
0 1.0 0.0 1
1 2.0 2.0 2
2 0.0 3.0 3
3 4.0 0.0 4
4 5.0 5.0 5
用平均值填补后:
A B C
0 1.0 3.3 1
1 2.0 2.0 2
2 3.0 3.0 3
3 4.0 3.3 4
4 5.0 5.0 5
用中位数填补后:
A B C
0 1.0 3.0 1
1 2.0 2.0 2
2 3.0 3.0 3
3 4.0 3.0 4
4 5.0 5.0 5

从输出结果可以看出,fillna()方法可以根据不同的参数,用不同的值来填补缺失值。使用平均值、中位数等统计值填补缺失值,可以尽量减少偏差。

3.2.2 前向/后向填充

前向/后向填充是指用缺失值前面/后面的值来填充缺失值。这种方法适用于时间序列数据,或者数据有一定顺序关系的情况。Pandas也提供了fillna()方法来实现前向/后向填充,通过method参数指定填充方法。method='ffill'表示前向填充,method='bfill'表示后向填充。

# 前向填充
df_fillna_ffill = df.fillna(method='ffill')
print("前向填充后:")
print(df_fillna_ffill)
# 后向填充
df_fillna_bfill = df.fillna(method='bfill')
print("后向填充后:")
print(df_fillna_bfill)

输出结果:

前向填充后:
A B C
0 1.0 NaN 1
1 2.0 2.0 2
2 2.0 3.0 3
3 4.0 3.0 4
4 5.0 5.0 5
后向填充后:
A B C
0 1.0 2.0 1
1 2.0 2.0 2
2 4.0 3.0 3
3 4.0 5.0 4
4 5.0 5.0 5

从输出结果可以看出,ffill方法用缺失值前面的值来填充缺失值,bfill方法用缺失值后面的值来填充缺失值。需要注意的是,ffill方法不能填充第一行的缺失值,bfill方法不能填充最后一行的缺失值。

3.2.3 插值填充

插值填充是指根据缺失值周围的数据,使用某种插值算法来估计缺失值。插值填充可以更准确地估计缺失值,但是也需要选择合适的插值算法。Pandas提供了interpolate()方法来实现插值填充,支持多种插值算法,例如线性插值、多项式插值、样条插值等。

# 线性插值
df_interpolate_linear = df.interpolate(method='linear')
print("线性插值后:")
print(df_interpolate_linear)
# 多项式插值
df_interpolate_poly = df.interpolate(method='polynomial', order=2)
print("多项式插值后:")
print(df_interpolate_poly)

输出结果:

线性插值后:
A B C
0 1.0 NaN 1
1 2.0 2.0 2
2 3.0 3.0 3
3 4.0 4.0 4
4 5.0 5.0 5
线性插值后:
A B C
0 1.0 NaN 1
1 2.0 2.0 2
2 3.0 3.0 3
3 4.0 4.0 4
4 5.0 5.0 5

从输出结果可以看出,interpolate()方法可以根据不同的插值算法,来估计缺失值。线性插值是最常用的插值算法,多项式插值可以更准确地估计缺失值,但是也需要选择合适的阶数。需要注意的是,插值填充需要数据有一定的规律性,如果数据没有规律性,插值填充的效果可能很差。

3.2.4 模型预测填充

对于复杂的数据,我们可以使用机器学习模型来预测缺失值。这种方法可以更准确地估计缺失值,但是需要构建和训练模型。例如,我们可以使用线性回归、决策树、随机森林等模型来预测缺失值。这种方法比较复杂,这里就不详细介绍了。

3.2.5 填补缺失值的注意事项

  • 填补缺失值会引入偏差,所以在使用fillna()方法时,一定要慎重选择填补方法,评估填补方法对分析结果的影响。
  • 不同的填补方法适用于不同的数据类型和缺失值情况,要根据实际情况选择合适的填补方法。
  • 在填补缺失值之前,最好先对缺失值的分布情况进行分析,了解缺失值的产生原因和规律,以便更好地选择填补策略。
  • 对于时间序列数据,前向/后向填充和插值填充是常用的方法。
  • 对于数值型数据,平均值、中位数、插值填充是常用的方法。
  • 对于分类数据,众数是常用的方法。
  • 如果数据比较复杂,可以使用模型预测填充。

4. 进阶技巧:处理更复杂的情况

除了基本的缺失值检测和处理方法,Pandas还提供了一些进阶技巧,可以帮助我们处理更复杂的情况。

4.1 多列缺失值处理

如果多列存在缺失值,我们可以使用fillna()方法结合groupby()方法来针对不同的分组进行填补。

# 创建一个包含多列缺失值的DataFrame
data = {
'A': [1, 1, 2, 2, 3, 3],
'B': [1, np.nan, 1, np.nan, np.nan, 3],
'C': [np.nan, 2, 3, 4, np.nan, 6]
}
df = pd.DataFrame(data)
# 按照列A进行分组,然后用每组的均值填充缺失值
df_fillna_group = df.groupby('A').transform(lambda x: x.fillna(x.mean()))
print("多列缺失值处理后:")
print(df_fillna_group)

输出结果:

多列缺失值处理后:
B C
0 1.0 2.5
1 1.0 2.0
2 1.0 3.0
3 1.0 4.0
4 3.0 6.0
5 3.0 6.0

从输出结果可以看出,groupby()方法可以将数据按照列A进行分组,然后使用transform()方法,对每组的数据进行缺失值填充。这里使用了均值进行填充,你可以根据实际情况选择不同的填充方法。

4.2 缺失值与异常值处理结合

异常值是指与数据集中其他值差异很大的值,例如,某个人的年龄是200岁,或者某个商品的销售价格是负数。异常值可能会影响数据分析结果,所以需要进行处理。处理异常值的方法有很多,例如,删除异常值、替换异常值、将异常值视为缺失值等。如果数据中既有缺失值,又有异常值,那么我们需要将缺失值处理和异常值处理结合起来。

# 创建一个包含缺失值和异常值的DataFrame
data = {
'A': [1, 2, np.nan, 4, 100],
'B': [np.nan, 2, 3, np.nan, 5]
}
df = pd.DataFrame(data)
# 将异常值(大于10)视为缺失值
df['A'] = df['A'].where(df['A'] <= 10, np.nan)
# 用平均值填充缺失值
df_fillna = df.fillna(df.mean())
print("缺失值和异常值处理结合后:")
print(df_fillna)

输出结果:

缺失值和异常值处理结合后:
A B
0 1.0 3.0
1 2.0 2.0
2 3.0 3.0
3 4.0 3.0
4 3.0 5.0

从输出结果可以看出,我们首先将异常值(大于10)视为缺失值,然后使用平均值填充缺失值。这样就将缺失值处理和异常值处理结合起来,保证了数据的质量。

4.3 复杂场景下的缺失值处理流程

在实际应用中,缺失值处理往往是一个复杂的过程,需要结合具体的数据情况和业务需求,制定合理的处理流程。以下是一个复杂场景下的缺失值处理流程:

  1. 数据探索: 首先,我们需要对数据进行探索,包括查看数据类型、数据分布、缺失值分布等,了解数据的整体情况和缺失值的特征。
  2. 缺失值检测: 使用isnull()notnull()info()等方法,检测数据中是否存在缺失值,以及缺失值的分布情况。
  3. 缺失值分析: 分析缺失值的产生原因和规律,判断缺失值是否具有随机性,是否与某些变量有关,以便更好地选择处理方法。
  4. 缺失值处理策略选择: 根据缺失值的产生原因和规律,以及数据的具体情况,选择合适的缺失值处理策略,例如删除缺失值、常数填补、前向/后向填充、插值填充、模型预测填充等。
  5. 缺失值处理实施: 使用Pandas提供的dropna()fillna()interpolate()等方法,实施缺失值处理策略。
  6. 数据质量评估: 评估缺失值处理后的数据质量,包括检查缺失值是否被正确处理,数据分布是否发生变化,以及对后续分析和建模的影响。
  7. 迭代优化: 根据数据质量评估结果,迭代优化缺失值处理流程,直到达到满意的效果。

5. 总结与最佳实践

处理缺失值是数据分析中非常重要的一步,也是一个充满挑战的过程。掌握Pandas中处理缺失值的各种方法,可以帮助我们轻松应对各种数据清洗难题。下面我给大家总结一下处理缺失值的最佳实践:

  • 充分理解数据: 在处理缺失值之前,一定要充分理解数据,包括数据的含义、数据类型、数据分布、缺失值的产生原因和规律等。只有理解了数据,才能选择合适的处理方法。
  • 选择合适的处理方法: 不同的处理方法适用于不同的数据类型和缺失值情况,要根据实际情况选择合适的处理方法。没有最好的方法,只有最适合的方法。
  • 重视数据质量评估: 缺失值处理后的数据质量评估非常重要,要检查缺失值是否被正确处理,数据分布是否发生变化,以及对后续分析和建模的影响。
  • 结合业务知识: 在处理缺失值的过程中,要结合业务知识,例如,某些变量的缺失值可能与某些业务场景有关,需要进行特殊处理。
  • 记录处理过程: 记录缺失值处理的过程,包括使用了哪些方法,以及处理后的数据质量如何。这样可以方便后续的复现和优化。

总而言之,处理缺失值需要耐心和细致。希望今天的分享能够帮助你更好地处理缺失值,为你的数据分析和建模打下坚实的基础。记住,数据清洗是数据分析的基础,只有数据干净,才能得到可靠的分析结果。加油!

6. 补充说明:一些常见问题和解答

  • Q: 为什么我的数据里会有缺失值?

    • A: 缺失值的原因有很多,例如:数据采集过程中出现错误,数据录入过程中出现错误,数据本身存在缺失,数据传输过程中出现错误,等等。理解缺失值的原因有助于选择合适的处理方法。
  • Q: 删除缺失值会损失数据,我应该怎么权衡?

    • A: 删除缺失值确实会损失数据,但是如果缺失值数量很少,或者缺失值对分析结果的影响很小,那么删除缺失值是一个不错的选择。如果缺失值数量很多,或者缺失值对分析结果的影响很大,那么删除缺失值可能不是一个好的选择。你可以通过比较删除缺失值前后分析结果的变化,来评估删除缺失值的影响。
  • Q: 应该用什么值来填补缺失值?

    • A: 应该用什么值来填补缺失值,取决于数据的类型和缺失值的分布情况。对于数值型数据,可以使用平均值、中位数、众数等来填补缺失值。对于分类数据,可以使用众数来填补缺失值。对于时间序列数据,可以使用前向/后向填充或插值填充。对于复杂的数据,可以使用模型预测填充。
  • Q: 如何判断填补缺失值是否合适?

    • A: 可以通过多种方法来判断填补缺失值是否合适,例如:比较填补缺失值前后数据分布的变化,比较填补缺失值前后分析结果的变化,以及评估填补缺失值对后续建模的影响。如果填补缺失值后,数据分布变化不大,分析结果变化不大,并且模型效果更好,那么说明填补缺失值是合适的。
  • Q: 缺失值处理的顺序重要吗?

    • A: 缺失值处理的顺序通常是重要的。一般来说,先进行缺失值检测,然后进行缺失值分析,最后选择合适的处理方法。在处理过程中,可能需要多次迭代,例如,先删除缺失值,然后进行数据分析,发现还有缺失值,再进行填补,等等。

7. 结束语

处理缺失值是一个不断学习和实践的过程。希望今天的分享能够帮助你更好地理解和掌握Pandas中处理缺失值的各种方法。如果你在实际工作中遇到任何问题,欢迎随时向我提问。让我们一起在数据分析的道路上不断前进!

希望这篇文章对你有所帮助!

老码农 pandas缺失值处理数据清洗数据分析

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/8780