3.4.2 缺失值的处理
在数据分析的过程中,缺失值(Missing Data)是一个常见且必须处理的重要问题。Python 中的 Pandas 库为我们提供了多种方法来处理缺失值,包括填充、删除和检查缺失值等功能。本文将介绍一些常见的处理缺失值的方法,并展示如何利用 Pandas 进行高效的缺失值操作。
1. 什么是缺失值?
缺失值是指数据集中缺少的数值,它通常以 None
或 np.nan
表示。
- None:是 Python 中的空对象,类型为
object
,通常不参与计算,计算时可能会耗时较长。 - np.nan:是 Pandas 中表示缺失数据的标准值,类型为
float
,可以参与计算,但会导致结果为空。
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(1, 10, (3, 4)))
df.loc[0, 1] = np.nan
df.loc[1, 2] = np.nan
df.loc[2, 3] = np.nan
print(df)
0 1 2 3
0 6.0 NaN 3.0 4.0
1 8.0 5.0 NaN 6.0
2 3.0 9.0 7.0 NaN
2. 处理缺失值的常用方法
2.1 使用 np.nansum()
忽略 NaN 值进行计算
在进行运算时,我们可以使用 np.nansum()
,它会忽略掉 NaN 值进行计算:
np.nansum(df) # 可以通过np.nan* 忽略nan进行运算
2.2 使用 isnull()
和 notnull()
检查缺失值
我们可以使用 pd.isnull()
或 pd.notnull()
来检查 DataFrame 中的缺失值。
isnull()
:判断元素是否为缺失值(NaN)。notnull()
:判断元素是否不是缺失值。
print(pd.isnull(df)) # 判断各元素是否为 NaN
print(pd.notnull(df)) # 判断各元素是否不是 NaN
2.3 使用 all()
和 any()
判断列或行是否包含 NaN
all()
:当所有值都是 NaN 时返回True
。any()
:只要有一个值是 NaN,就返回True
。
print(pd.isnull(df).all()) # 检查每一列是否全部为 NaN
print(pd.isnull(df).any()) # 检查每一列是否有 NaN
print(pd.isnull(df).all(axis=1)) # 检查每一行是否全部为 NaN
print(pd.isnull(df).any(axis=1)) # 检查每一行是否有 NaN
2.4 过滤空值(NaN)
2.4.1 行过滤
我们可以通过布尔值过滤缺失值。如果一行中含有 NaN 值,则返回 True
:
condition = pd.isnull(df).any(axis=1)
print(df[~condition]) # 筛选不包含 NaN 的行
2.4.2 列过滤
我们可以检查每一列是否包含 NaN 值,如果有则返回 True
:
condition = pd.isnull(df).any()
print(df.loc[:, ~condition]) # 筛选不包含 NaN 的列
2.4.3 使用 dropna()
删除缺失值
dropna()
是一个非常方便的方法,可以直接删除包含缺失值的行或列。
# 默认删除包含空值的行
print(df.dropna())
# 删除包含空值的列
print(df.dropna(axis=1))
# 只要全是 NaN 才会删除
print(df.dropna(how='all'))
# 删除包含任何 NaN 值的行
print(df.dropna(how='any'))
# 使用 inplace=True,直接修改原 DataFrame
df.dropna(inplace=True)
print(df)
2.5 使用 fillna()
填充缺失值
fillna()
方法可以用来填充缺失值。我们可以指定填充的值,或者使用前后值进行填充。
- 填充指定值:通过
value
参数指定一个值来填充缺失值。
df.fillna(value=100)
- 限制填充数量:使用
limit
参数限制最多填充多少个 NaN 值。
df.fillna(value=66, limit=2) # 最多填充 2 个 NaN
- 使用前后值填充:
method='ffill'
:使用前一个值填充 NaN。method='bfill'
:使用后一个值填充 NaN。
df.fillna(method='ffill', limit=2) # 使用前一个非 NaN 值填充
df.fillna(method='backfill', limit=2) # 使用下一个非 NaN 值填充
- 使用
inplace=True
修改原 DataFrame:
df.fillna(value=66, inplace=True) # 直接修改 df
3.4.3 重复数据处理
在数据分析中,清洗数据是非常重要的一部分,尤其是当你有重复的数据时。Pandas 提供了强大的方法来帮助我们识别和处理重复数据。本文将通过一个简单的示例来讲解如何在 Pandas 中查找和删除重复数据。
示例数据
import pandas as pd
data = {
"学号": ["2022000001", "2022000001", "2022000002", "2022000003"],
"姓名": ["zhangsan", "lisi", "wangwu", "zhaoliu"],
"性别": ["男", "男", "女", "女"]
}
df = pd.DataFrame(data)
print(df)
输出如下:
学号 姓名 性别
0 2022000001 zhangsan 男
1 2022000001 lisi 男
2 2022000002 wangwu 女
3 2022000003 zhaoliu 女
我们注意到,学号为 2022000001
的学生有重复的记录。这时候我们就需要处理重复数据,确保每个学生的学号只有一条记录。
- 判断重复数据
- 判断是否有重复值
首先,我们可以使用 duplicated()
方法来判断整个 DataFrame 是否有重复的记录。该方法会返回一个布尔型的 Series,True
表示该行是重复的,False
表示该行是唯一的。
df.duplicated()
2.针对某一列判断重复值
有时我们可能只关心某一列的重复数据,比如在本例中我们只关心学号(学号
)是否有重复。在这种情况下,我们可以使用 duplicated(subset=["学号"])
方法。
df.duplicated(subset=["学号"])
输出:
0 True
1 False
2 False
3 False
dtype: bool
可以看到,只有学号为 2022000001
的第一行被标记为重复。
- 保留重复项的特定行
有时候我们希望删除重复的行,但要保留某一行,比如保留重复项的第一条记录或最后一条记录。可以通过设置 keep
参数来实现。
- 保留第一行:使用
keep="first"
,默认行为。
df.duplicated(subset=["学号"], keep="first")
输出:
0 True
1 False
2 False
3 False
dtype: bool
- 保留最后一行:使用
keep="last"
。
pythondf.duplicated(subset=["学号"], keep="last")
输出:
0 False
1 True
2 False
3 False
dtype: bool
- 不保留任何重复项
如果你想删除所有重复的行,可以使用 keep=False
。这会标记所有重复的行。
df.duplicated(subset=["学号"], keep=False)
输出:
0 True
1 True
2 False
3 False
dtype: bool
- 删除重复的数据
一旦我们识别了重复的数据,就可以使用 drop_duplicates()
方法删除这些重复的行。drop_duplicates()
方法可以通过 subset
参数指定要检查重复的列,通过 keep
参数指定要保留的重复项。
- 删除重复行(保留第一条记录)
我们可以通过 keep="first"
保留第一次出现的记录,删除后续的重复记录:
df.drop_duplicates(subset=["学号"], keep="first", inplace=True)
print(df)
输出:
学号 姓名 性别
0 2022000001 zhangsan 男
2 2022000002 wangwu 女
3 2022000003 zhaoliu 女
- 删除重复行(保留最后一条记录)
如果我们希望保留最后一条记录,可以使用 keep="last"
:
df.drop_duplicates(subset=["学号"], keep="last", inplace=True)
print(df)
输出:
学号 姓名 性别
1 2022000001 lisi 男
2 2022000002 wangwu 女
3 2022000003 zhaoliu 女
- 删除所有重复行
如果我们希望删除所有重复的记录(即删除所有重复学号的行),可以使用 keep=False
:
df.drop_duplicates(subset=["学号"], keep=False, inplace=True)
print(df)
输出:
学号 姓名 性别
2 2022000002 wangwu 女
3 2022000003 zhaoliu 女