
Python中处理Pandas的缺失值(NaN)是数据清洗的关键一步,核心在于根据数据特性和分析目标,选择删除、填充或更复杂的插值策略,以确保数据质量和分析的准确性。这并非一个一劳永逸的方案,而是需要结合实际业务场景深思熟虑的决策过程。
处理Pandas中的NaN值,通常涉及识别、删除、填充和插值这几个主要步骤。
1. 识别缺失值 在动手处理之前,我们得先知道缺失值在哪儿,有多少。
import pandas as pd
import numpy as np
# 示例数据
data = {
'A': [1, 2, np.nan, 4, 5],
'B': [np.nan, 2, 3, 4, np.nan],
'C': [1, 2, 3, 4, 5],
'D': [np.nan, np.nan, np.nan, 4, 5]
}
df = pd.DataFrame(data)
print("原始DataFrame:\n", df)
# 检查每个元素是否为NaN
print("\n缺失值布尔矩阵:\n", df.isnull())
# 统计每列的缺失值数量
print("\n每列缺失值数量:\n", df.isnull().sum())
# 统计总缺失值数量
print("\n总缺失值数量:", df.isnull().sum().sum())
# 检查非缺失值
print("\n非缺失值布尔矩阵:\n", df.notnull())2. 删除缺失值 (dropna()
# 删除包含任何NaN的行
df_dropped_rows = df.dropna()
print("\n删除包含任何NaN的行:\n", df_dropped_rows)
# 删除包含任何NaN的列
df_dropped_cols = df.dropna(axis=1)
print("\n删除包含任何NaN的列:\n", df_dropped_cols)
# 删除所有值都为NaN的行
df_dropped_all_nan_rows = df.dropna(how='all')
print("\n删除所有值都为NaN的行:\n", df_dropped_all_nan_rows)
# 删除指定列中存在NaN的行 (例如,只关心'A'列和'B'列的完整性)
df_dropped_subset = df.dropna(subset=['A', 'B'])
print("\n删除'A'或'B'列有NaN的行:\n", df_dropped_subset)
# 删除至少有N个非NaN值的行 (例如,至少有3个非NaN值才保留该行)
df_thresh = df.dropna(thresh=3)
print("\n保留至少有3个非NaN值的行:\n", df_thresh)3. 填充缺失值 (fillna()
# 用一个常数填充所有NaN
df_filled_const = df.fillna(0)
print("\n用0填充所有NaN:\n", df_filled_const)
# 用每列的均值填充NaN
df_filled_mean = df.fillna(df.mean(numeric_only=True))
print("\n用每列均值填充NaN:\n", df_filled_mean)
# 用每列的中位数填充NaN
df_filled_median = df.fillna(df.median(numeric_only=True))
print("\n用每列中位数填充NaN:\n", df_filled_median)
# 用每列的众数填充NaN (注意众数可能不止一个,这里取第一个)
df_filled_mode = df.fillna(df.mode().iloc[0])
print("\n用每列众数填充NaN:\n", df_filled_mode)
# 前向填充 (用前一个有效值填充)
df_ffill = df.fillna(method='ffill')
print("\n前向填充:\n", df_ffill)
# 后向填充 (用后一个有效值填充)
df_bfill = df.fillna(method='bfill')
print("\n后向填充:\n", df_bfill)
# 限制填充次数 (例如,最多填充1个NaN)
df_ffill_limit = df.fillna(method='ffill', limit=1)
print("\n前向填充,限制一次:\n", df_ffill_limit)
# 对特定列进行填充
df_specific_fill = df.copy()
df_specific_fill['A'] = df_specific_fill['A'].fillna(df_specific_fill['A'].mean())
df_specific_fill['B'] = df_specific_fill['B'].fillna('未知') # 假设B是分类数据
print("\n对特定列进行填充:\n", df_specific_fill)4. 插值处理 (interpolate()
# 线性插值
df_interpolated_linear = df.interpolate(method='linear')
print("\n线性插值:\n", df_interpolated_linear)
# 限制插值方向和次数
df_interpolated_limit = df.interpolate(method='linear', limit_direction='forward', limit=1)
print("\n线性插值,向前限制一次:\n", df_interpolated_limit)
# 多项式插值 (需要安装scipy)
# df_interpolated_poly = df.interpolate(method='polynomial', order=2)
# print("\n多项式插值 (order=2):\n", df_interpolated_poly)
# 时间序列插值 (需要索引是时间戳)
df_ts = pd.DataFrame({'value': [1, 2, np.nan, 4, 5, np.nan, 7]},
index=pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05', '2023-01-07', '2023-01-08']))
df_ts_interpolated = df_ts.interpolate(method='time')
print("\n时间序列插值:\n", df_ts_interpolated)说实话,每次看到数据框里一大堆
NaN
最常见的几种情况:
立即学习“Python免费学习笔记(深入)”;
NaN
NaN
NaN
inf
NaN
NaN
np.nan
这些原因决定了我们后续处理
NaN
NaN
dropna()
fillna()
这真是一个“世纪难题”,没有哪个方法是绝对的好或绝对的坏,它完全取决于你的数据、你的分析目标以及你对“真实性”的容忍度。在我多年的数据处理经验中,我发现这更像是一场权衡利弊的博弈。
什么时候我会倾向于 dropna()
NaN
dropna()
但话说回来,
dropna()
那么,什么时候我会更青睐 fillna()
fillna()
ffill
bfill
我的个人观点: 绝大多数情况下,我都会优先考虑
fillna()
dropna()
NaN
当我们决定用
fillna()
填充的“陷阱”:
bfill
ffill
高级技巧:
分组填充 (groupby().transform()
# 假设我们有一个DataFrame,包含城市和收入,有些收入缺失
df_group = pd.DataFrame({
'City': ['A', 'A', 'B', 'B', 'A', 'B', 'A', 'B'],
'Income': [5000, 6000, 7000, np.nan, np.nan, 8000, 5500, np.nan]
})
print("原始分组数据:\n", df_group)
# 按城市分组,然后用每个城市的平均收入填充缺失值
df_group['Income_filled'] = df_group.groupby('City')['Income'].transform(lambda x: x.fillna(x.mean()))
print("\n按城市分组填充收入:\n", df_group)transform
更复杂的插值方法 (interpolate()
interpolate()
polynomial
spline
pchip
method='time'
# 示例,更复杂的插值,需要数据有一定趋势
s = pd.Series([0, 1, np.nan, np.nan, 5, 6])
print("\n原始Series:\n", s)
print("多项式插值 (order=2):\n", s.interpolate(method='polynomial', order=2))
# print("样条插值 (order=2):\n", s.interpolate(method='spline', order=2)) # 需要scipy选择哪种插值方法,需要对数据背后生成机制有一定理解,或者通过交叉验证来选择最优方法。
基于模型预测缺失值: 这是最“硬核”的缺失值处理方法之一。你可以把缺失值所在的列当作目标变量,用其他列作为特征,训练一个机器学习模型(比如线性回归、决策树、KNN等)来预测缺失值。例如,Scikit-learn库中的
IterativeImputer
KNNImputer
添加缺失值指示变量: 有时候,缺失本身就是一种信息。例如,用户没有填写年龄,可能意味着他们不想透露,或者年龄不适用。在这种情况下,你可以创建一个新的二元变量(0或1),表示原始数据点是否缺失。然后,即使你用某种方法填充了原始缺失值,这个指示变量也能让你的模型知道哪些数据点最初是缺失的。这可以帮助模型捕捉缺失值可能带来的特殊含义。
处理缺失值,没有银弹。在我看来,最重要的就是理解你的数据和你的分析目的。多尝试不同的方法,并评估它们对最终结果的影响,才是王道。
以上就是python中pandas如何处理缺失值(NaN)?的详细内容,更多请关注php中文网其它相关文章!
python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号