3.1 缺失值处理 3.1 缺失值处理 在数据分析和机器学习项目中,真实世界的数据往往是不完整的。缺失值(Missing Values)是数据集中常见的问题,它们可能由于各种原因产生,例如数据采集错误、信息丢失、数据损坏或未填写字段等。处理缺失值是数据清洗和预处理的关键步骤,直接影响后续分析和建模的准确性和可靠性。 3.1.1 缺失值的类型 了解缺失值的类型有助于选择合适的处理方法。常见的缺失值类型包括: 完全随机缺失 (Missing Completely at Random, MCAR): 数据缺失与其他任何变量都无关,包括观测变量和未观测变量。例如,问卷调查中随机跳过某些问题。
在数据分析和机器学习项目中,真实世界的数据往往是不完整的。缺失值(Missing Values)是数据集中常见的问题,它们可能由于各种原因产生,例如数据采集错误、信息丢失、数据损坏或未填写字段等。处理缺失值是数据清洗和预处理的关键步骤,直接影响后续分析和建模的准确性和可靠性。
了解缺失值的类型有助于选择合适的处理方法。常见的缺失值类型包括:
完全随机缺失 (Missing Completely at Random, MCAR): 数据缺失与其他任何变量都无关,包括观测变量和未观测变量。例如,问卷调查中随机跳过某些问题。
随机缺失 (Missing at Random, MAR): 数据缺失与某些观测变量有关,但与未观测变量无关。例如,男性更不愿意透露自己的体重,则体重缺失与性别有关。
非随机缺失 (Missing Not at Random, MNAR): 数据缺失与自身的值有关。例如,收入较低的人更不愿意透露自己的收入。
在 Pandas 中,缺失值通常用 NaN (Not a Number) 表示,它是 float 类型。Pandas 提供了一些方法来识别缺失值:
isnull():检测 DataFrame 或 Series 中的缺失值,返回布尔值,True 表示缺失值。
notnull():与 isnull() 相反,返回布尔值,True 表示非缺失值。
isna():isnull() 的别名,功能相同。
notna():notnull() 的别名,功能相同。
代码示例:
import pandas as pd import numpy as np # 创建包含缺失值的 DataFrame data = {'A': [1, 2, np.nan, 4], 'B': [5, np.nan, 7, 8], 'C': [9, 10, 11, np.nan]} df = pd.DataFrame(data) print("原始 DataFrame:\n", df) # 检测缺失值 print("\n缺失值检测 (isnull()):\n", df.isnull()) # 检测非缺失值 print("\n非缺失值检测 (notnull()):\n", df.notnull()) # 统计每列的缺失值数量 print("\n每列缺失值数量:\n", df.isnull().sum()) # 统计每行的缺失值数量 print("\n每行缺失值数量:\n", df.isnull().sum(axis=1)) # 统计缺失值总数 print("\n缺失值总数:\n", df.isnull().sum().sum())
代码解释:
首先,使用 pandas 和 numpy 创建一个包含 NaN 值的 DataFrame。
isnull() 方法返回一个布尔 DataFrame,其中 True 表示缺失值,False 表示非缺失值。
notnull() 方法与 isnull() 相反。
df.isnull().sum() 统计每列的缺失值数量。axis=1 则统计每行的缺失值数量。
df.isnull().sum().sum() 统计 DataFrame 中缺失值的总数。
处理缺失值的方法取决于数据的性质、缺失值的数量和类型,以及分析的目标。常见的处理方法包括:
删除缺失值 (Deletion):
删除包含缺失值的行 (Listwise Deletion): 删除包含任何缺失值的行。适用于缺失值数量较少且为 MCAR 的情况。
删除包含缺失值的列 (Columnwise Deletion): 删除包含过多缺失值的列。适用于该列对分析不重要的情况。
代码示例:
# 删除包含缺失值的行 df_dropna_row = df.dropna() print("\n删除包含缺失值的行:\n", df_dropna_row) # 删除包含缺失值的列 (当缺失值超过阈值时删除) threshold = len(df) * 0.5 # 阈值为行数的 50% df_dropna_col = df.dropna(axis=1, thresh=threshold) print("\n删除包含缺失值的列:\n", df_dropna_col)
代码解释:
df.dropna() 删除包含任何缺失值的行。
df.dropna(axis=1, thresh=threshold) 删除缺失值数量超过阈值的列。axis=1 表示按列删除,thresh 参数指定保留至少有多少个非缺失值。
填充缺失值 (Imputation):
常量填充 (Constant Imputation): 使用一个固定的值填充缺失值,例如 0、-1 或 "Missing"。
均值/中位数/众数填充 (Mean/Median/Mode Imputation): 使用列的均值、中位数或众数填充缺失值。适用于数值型数据。
回归/插值填充 (Regression/Interpolation Imputation): 使用回归模型或插值方法预测缺失值。适用于缺失值与其它变量存在关系的情况。
多重插补 (Multiple Imputation): 生成多个完整的数据集,每个数据集都包含不同的缺失值填充方案,然后对这些数据集进行分析,最后将结果合并。
代码示例:
# 常量填充 df_fillna_constant = df.fillna(0) print("\n常量填充:\n", df_fillna_constant) # 均值填充 df_fillna_mean = df.fillna(df.mean()) print("\n均值填充:\n", df_fillna_mean) # 中位数填充 df_fillna_median = df.fillna(df.median()) print("\n中位数填充:\n", df_fillna_median) # 前向/后向填充 df_fillna_ffill = df.fillna(method='ffill') # 使用前一个非缺失值填充 print("\n前向填充:\n", df_fillna_ffill) df_fillna_bfill = df.fillna(method='bfill') # 使用后一个非缺失值填充 print("\n后向填充:\n", df_fillna_bfill)
代码解释:
df.fillna(0) 使用 0 填充所有缺失值。
df.fillna(df.mean()) 使用每列的均值填充缺失值。
df.fillna(df.median()) 使用每列的中位数填充缺失值。
df.fillna(method='ffill') 使用前向填充,将缺失值替换为前一个非缺失值。
df.fillna(method='bfill') 使用后向填充,将缺失值替换为后一个非缺失值。
使用特定值标记缺失值:
代码示例:
# 使用字符串标记缺失值 df_fillna_string = df.fillna("Missing") print("\n使用字符串标记缺失值:\n", df_fillna_string)
代码解释:
df.fillna("Missing") 使用字符串 "Missing" 填充所有缺失值。选择合适的缺失值处理方法需要考虑以下因素:
缺失值的数量: 如果缺失值数量较少,可以直接删除包含缺失值的行。如果缺失值数量较多,则需要考虑填充或使用其他方法。
缺失值的类型: 如果缺失值是 MCAR 或 MAR,则可以使用均值/中位数填充。如果缺失值是 MNAR,则需要使用更复杂的模型进行填充。
数据的性质: 对于数值型数据,可以使用均值/中位数填充或回归/插值填充。对于类别型数据,可以使用众数填充或使用特定值标记。
分析的目标: 不同的缺失值处理方法可能会对分析结果产生不同的影响。需要根据分析的目标选择合适的处理方法。
以下是一个通用的缺失值处理流程图:
流程图解释:
开始: 从原始数据开始。
识别缺失值: 使用 isnull() 或 isna() 方法识别缺失值。
分析缺失值类型和数量: 确定缺失值的类型(MCAR、MAR 或 MNAR)和数量。
缺失值数量是否过多?: 如果缺失值数量过多,则考虑删除包含过多缺失值的列。
缺失值类型是 MCAR/MAR?: 如果缺失值是 MCAR 或 MAR,则可以使用均值/中位数/众数填充。
回归/插值/多重插补: 如果缺失值是 MNAR,则需要使用更复杂的模型进行填充。
删除列: 删除包含过多缺失值的列。
应用填充方法: 使用选择的填充方法填充缺失值。
验证填充结果: 验证填充结果是否合理。
结束: 完成缺失值处理。
缺失值处理是数据清洗和预处理的重要步骤。选择合适的处理方法需要考虑多种因素,包括缺失值的数量和类型、数据的性质以及分析的目标。通过合理地处理缺失值,可以提高数据分析和建模的准确性和可靠性。 Pandas 提供了强大的工具来识别和处理缺失值,使得数据科学家能够有效地处理这些常见的数据问题。