数据清洗中的缺失值预处理主要包括识别、分析、选择策略并执行。1. 识别缺失值:使用isnull()或isna()判断缺失情况,并用sum()统计缺失数量。2. 分析缺失模式:判断缺失是否随机,是否与其他列有关联。3. 选择处理策略:包括删除(dropna)和填充(fillna)。删除适用于缺失值较少或列缺失严重的情况;填充包括均值、中位数、众数、前后向填充、插值等方法,分别适用于不同数据类型和结构。4. 评估处理效果:检查缺失值是否清除,分析数据分布变化、特征相关性变化,并通过简单模型验证处理效果。处理缺失值需结合数据特性、缺失类型和分析目标,避免“过度清洗”带来的偏差。

Python数据清洗,特别是缺失值预处理,是数据分析流程中一个至关重要且充满挑战的环节。它不仅仅是技术操作,更是一门艺术,核心在于识别、理解缺失模式,并选择最合适的填充或删除策略,这背后是对数据本身深入洞察的过程。

处理缺失值,我们通常会借助强大的Pandas库。整个过程可以概括为:识别、分析、选择策略并执行。
识别缺失值:
在Pandas中,我们用isnull()或isna()来判断数据框中的每一个元素是否为缺失值(通常表现为NaN, None或NaT)。接着,用.sum()方法可以快速统计每个列的缺失值数量,这能给我们一个初步的全局视图。

import pandas as pd
import numpy as np
# 示例数据
data = {
'A': [1, 2, np.nan, 4, 5],
'B': [np.nan, 2, 3, 4, 5],
'C': [1, 2, 3, np.nan, np.nan],
'D': ['apple', 'banana', 'cherry', np.nan, 'grape']
}
df = pd.DataFrame(data)
print("原始数据框:")
print(df)
print("\n各列缺失值数量:")
print(df.isnull().sum())分析缺失模式: 仅仅知道有多少缺失值还不够。我们还需要思考:这些缺失值是随机的吗?它们之间有什么关联?例如,如果某个用户没有填写年龄,是不是也常常没有填写收入?这种洞察力往往比单纯的技术操作更有价值。
处理策略选择与执行:
立即学习“Python免费学习笔记(深入)”;

删除(Deletion):
df.dropna()。如果一行中包含任何缺失值,就删除整行。这适用于缺失值占比较小,且我们不希望引入任何偏差的情况。但要小心,过度删除可能导致数据量锐减,丢失宝贵信息。df.dropna(axis=1)。如果某一列的缺失值过多,或者该列对分析目标不重要,可以直接删除。subset参数可以指定在哪些列中检查缺失值。how参数可以指定是“any”(任意一个缺失值就删除)还是“all”(所有值都缺失才删除)。# 删除含有任何缺失值的行
df_cleaned_rows = df.dropna()
print("\n删除含有缺失值的行后:")
print(df_cleaned_rows)
# 删除所有值都为缺失值的列(这里没有这样的列)
df_cleaned_cols = df.dropna(axis=1, how='all')
print("\n删除所有值都为缺失值的列后:")
print(df_cleaned_cols)填充(Imputation): df.fillna()
df['column'].fillna(df['column'].mean())。适用于数值型数据且分布近似正态。df['column'].fillna(df['column'].median())。适用于数值型数据,尤其当数据存在异常值或偏态分布时,中位数更稳健。df['column'].fillna(df['column'].mode()[0])。适用于类别型或数值型离散数据。df.ffill()或df.bfill()。ffill()(forward fill):用前一个有效值填充当前缺失值。bfill()(backward fill):用后一个有效值填充当前缺失值。
特别适用于时间序列数据,假设缺失值与前后数据点有内在关联。df.interpolate()。method='linear'进行线性插值。对于数值型数据,特别是存在趋势的数据,这是一种更精细的填充方法。# 均值填充(适用于数值列)
df_filled_mean = df.copy()
df_filled_mean['A'] = df_filled_mean['A'].fillna(df_filled_mean['A'].mean())
print("\n'A'列均值填充后:")
print(df_filled_mean)
# 众数填充(适用于类别列或离散数值列)
df_filled_mode = df.copy()
df_filled_mode['D'] = df_filled_mode['D'].fillna(df_filled_mode['D'].mode()[0])
print("\n'D'列众数填充后:")
print(df_filled_mode)
# 前向填充
df_ffill = df.copy()
df_ffill['C'] = df_ffill['C'].ffill()
print("\n'C'列前向填充后:")
print(df_ffill)
# 线性插值
df_interpolated = df.copy()
df_interpolated['B'] = df_interpolated['B'].interpolate(method='linear')
print("\n'B'列线性插值后:")
print(df_interpolated)更高级的方法: 机器学习模型(如KNNImputer, IterativeImputer)可以根据其他特征来预测缺失值,但通常计算成本更高,且需要更复杂的设置。
数据缺失是一个普遍存在的问题,它背后原因复杂多样,绝非仅仅是“没数据”那么简单。在我看来,理解这些“为什么”比知道“怎么填”更为关键,因为它直接影响我们后续选择的处理策略。
常见原因:
缺失数据类型(这才是真正需要我们深思的):
完全随机缺失(Missing Completely At Random, MCAR): 这是一种理想状态。缺失的发生与任何可观测变量和未观测变量都无关。比如,数据录入员不小心跳过了一个单元格,这个跳过是随机的。如果数据是MCAR,那么我们直接删除含有缺失值的行,对分析结果的偏差影响最小。但现实中,MCAR非常罕见。
随机缺失(Missing At Random, MAR): 缺失的发生与其他可观测变量有关,但与缺失变量本身的未观测值无关。举个例子,女性受访者可能比男性受访者更倾向于不填写收入信息。在这种情况下,收入的缺失与性别有关,但与收入本身的真实值无关。处理MAR数据时,我们可以利用其他已知变量来推断缺失值,比如通过回归、插值等方法。
非随机缺失(Missing Not At Random, MNAR): 这是最棘手的情况。缺失的发生与缺失变量本身的未观测值有关。例如,收入特别高或特别低的人可能更倾向于不填写收入信息。这种情况下,缺失值本身就包含了重要信息。如果简单地删除或填充,可能会引入严重的偏差,导致模型结论失真。处理MNAR数据需要更复杂的统计模型或领域知识,有时甚至需要重新设计数据收集方案。
缺失值的影响:
因此,在处理缺失值之前,花时间去理解数据是如何缺失的,这远比盲目地应用某种填充方法更为重要。它决定了我们能否真正从数据中提取出有价值的信息。
选择合适的缺失值处理策略,就像是医生给病人开药方,没有万能药,只有最适合当前“病情”的方案。这需要我们结合数据的特性、缺失的模式以及最终的分析目标来做决策。下面我将结合Pandas的实际操作,聊聊我的选择逻辑。
1. 缺失值可视化与初步判断:
在动手处理前,我通常会先用可视化手段看看缺失值的分布。比如,missingno库就能绘制出非常直观的缺失值矩阵或条形图,帮助我们快速识别缺失模式。
# 假设df是你的DataFrame
import missingno as msno
import matplotlib.pyplot as plt
msno.matrix(df, figsize=(10, 5))
plt.title('Missing Value Matrix')
plt.show()
msno.bar(df, figsize=(10, 5))
plt.title('Missing Value Bar Chart')
plt.show()通过这些图,我能大致判断哪些列缺失严重,哪些列缺失可能与其他列相关联。
2. 策略选择考量与Pandas实战:
删除行/列 (dropna):
# 示例:如果'C'列缺失值过多,且对分析不重要,可以考虑删除
if df['C'].isnull().sum() / len(df) > 0.5: # 假设阈值是50%
df_new = df.drop(columns=['C'])
print("\n'C'列缺失过多,删除后:")
print(df_new)均值/中位数/众数填充 (fillna):
# 假设'A'列是数值型,偏态分布,用中位数填充
df_filled_median = df.copy()
df_filled_median['A'] = df_filled_median['A'].fillna(df_filled_median['A'].median())
print("\n'A'列中位数填充后:")
print(df_filled_median)
# 假设'D'列是类别型,用众数填充
df_filled_mode_D = df.copy()
df_filled_mode_D['D'] = df_filled_mode_D['D'].fillna(df_filled_mode_D['D'].mode()[0])
print("\n'D'列众数填充后:")
print(df_filled_mode_D)前后向填充 (ffill/bfill):
# 假设df是时间序列数据,'B'列有缺失,用前向填充
df_ts = pd.DataFrame({'value': [10, 12, np.nan, 15, np.nan, np.nan, 20]})
df_ts_ffill = df_ts.ffill()
print("\n时间序列数据前向填充后:")
print(df_ts_ffill)插值填充 (interpolate):
method='linear',因为它简单且有效。对于更复杂的模式,也可以尝试'polynomial'或'spline'。# 假设'B'列是数值型,存在线性趋势,用线性插值
df_interpolated_B = df.copy()
df_interpolated_B['B'] = df_interpolated_B['B'].interpolate(method='linear')
print("\n'B'列线性插值后:")
print(df_interpolated_B)总结一下我的选择逻辑:
这是一个迭代和实验的过程,没有一劳永逸的方案。
当我们完成了缺失值处理,无论是删除还是填充,我都觉得这只是完成了第一步。接下来的“评估”环节,在我看来,才是真正体现数据分析师功力的地方。如果不做评估,我们很可能就掉进了“过度清洗”的陷阱,最终得到一个看起来很完美,实则漏洞百出的数据集。
1. 再次确认缺失值是否已处理干净:
最直接的,就是再运行一次df.isnull().sum()。确保所有列的缺失值数量都变成了0(或者符合你处理后的预期)。
# 假设df_processed是处理后的DataFrame
print("\n处理后各列缺失值数量:")
print(df_processed.isnull().sum())如果还有,那说明处理逻辑有漏网之鱼,需要回溯。
2. 检查数据分布的变化: 这是关键!填充操作会改变数据的原始分布,而这种改变是否合理,直接影响后续分析的准确性。
数值型特征:
df.describe()的结果,特别是均值、中位数、标准差等,看它们的变化是否在可接受范围内。类别型特征:
# 示例:假设'A'列处理前后对比
# fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# df['A'].hist(ax=axes[0], bins=10)
# axes[0].set_title('Original A Distribution')
# df_processed['A'].hist(ax=axes[1], bins=10)
# axes[1].set_title('Processed A Distribution')
# plt.show()
# print(df['A'].describe())
# print(df_processed['A'].describe())3. 评估特征之间的关系(相关性): 填充操作可能会改变特征之间的相关性。例如,你用特征B的均值填充了特征A的缺失值,那么特征A和B之间的相关性可能会被削弱或扭曲。使用热力图或散点图矩阵来观察处理前后特征相关性的变化。
# 示例:处理前后相关性矩阵对比
# import seaborn as sns
# sns.heatmap(df.corr(), annot=True, cmap='coolwarm')
# plt.title('Original Correlation Matrix')
# plt.show()
# sns.heatmap(df_processed.corr(), annot=True, cmap='coolwarm')
# plt.title('Processed Correlation Matrix')
# plt.show()4. 运行简单的模型或分析任务: 这是最直接的验证方法。用处理前后的数据分别跑一个简单的模型(比如线性回归、决策树),看看模型的性能(R-squared
以上就是Python如何做数据清洗?预处理缺失值方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号