趋近智
数据集很少是完整的。缺失值,通常表示为 NaN(非数字)、None 或其他占位符,由于数据录入错误、传感器故障或受访者跳过问题而很常见。Scikit-learn 中的大多数机器学习算法无法直接处理缺失值,如果在训练或预测时遇到它们,将引发错误。因此,处理缺失数据是预处理流程中的必要一步。
有几种方法可以处理缺失值,每种方法都有其优缺点。
在决定策略之前,您首先需要识别缺失值所在的位置。Pandas DataFrame 为此提供了便利的方法:
import pandas as pd
import numpy as np
# 含有缺失值的示例 DataFrame
data = {'Age': [25, 30, np.nan, 35, 40],
'Salary': [50000, 60000, 75000, np.nan, 90000],
'City': ['New York', 'London', 'Paris', 'Tokyo', np.nan]}
df = pd.DataFrame(data)
print("DataFrame:")
print(df)
# 检查缺失值(返回布尔型 DataFrame)
print("\n缺失值检查:")
print(df.isnull())
# 获取每列缺失值的数量
print("\n每列缺失值数量:")
print(df.isnull().sum())
此输出有助于量化每个特征中缺失数据问题的程度。
一种直接的方法是简单地删除含有缺失值的数据点或特征。
df.dropna() 来完成此操作。df.drop() 删除整个列。然而,这应谨慎进行,因为即使是含有许多缺失值的列也可能保留一些预测能力。删除通常不是首选方法,除非缺失数据量非常小或某一列明显无法使用。
填充涉及用替代估计值来填补缺失值。这可以保持数据集的大小,但需要仔细考虑填充方法,以避免引入偏差或扭曲数据分布。Scikit-learn 在其 impute 模块中提供了 SimpleImputer 类,用于基本的填充任务。
SimpleImputer 的工作方式与其他 Scikit-learn 转换器类似,遵循熟悉的 fit 和 transform 模式。
此策略将数值列中的缺失值替换为该列中观测值的均值。
此策略将数值列中的缺失值替换为观测值的中位数。
此策略将缺失值替换为列中最常见的值(众数)。
此策略将缺失值替换为用户指定的固定常量值(例如,0、-1 或“缺失”)。
让我们看看如何使用 SimpleImputer 应用这些策略。我们将使用之前创建的示例 DataFrame。
from sklearn.impute import SimpleImputer
import numpy as np
import pandas as pd
# 示例 DataFrame(同上)
data = {'Age': [25, 30, np.nan, 35, 40],
'Salary': [50000, 60000, 75000, np.nan, 90000],
'City': ['New York', 'London', 'Paris', 'Tokyo', np.nan]}
df = pd.DataFrame(data)
# 分离数值列和类别列用于填充
df_numeric = df[['Age', 'Salary']]
df_categorical = df[['City']]
# --- 均值填充(针对数值)---
mean_imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
# 在数据上进行拟合以学习均值
mean_imputer.fit(df_numeric)
# 转换数据(替换 NaN)
df_numeric_mean_imputed = mean_imputer.transform(df_numeric)
print("\n均值填充后的数值数据:")
# 转换回 DataFrame 以便清晰显示
print(pd.DataFrame(df_numeric_mean_imputed, columns=df_numeric.columns))
# --- 中位数填充(针对数值)---
median_imputer = SimpleImputer(missing_values=np.nan, strategy='median')
median_imputer.fit(df_numeric)
df_numeric_median_imputed = median_imputer.transform(df_numeric)
print("\n中位数填充后的数值数据:")
print(pd.DataFrame(df_numeric_median_imputed, columns=df_numeric.columns))
# --- 最常见值填充(针对类别)---
# 注意:SimpleImputer 适用于数值表示。
# 对于类别数据,您通常会在编码*之后*应用此方法,
# 或者在编码之前直接使用 Pandas 的 fillna。
# 这里我们直接应用它进行演示,它会将字符串视为“对象”。
most_frequent_imputer = SimpleImputer(missing_values=np.nan, strategy='most_frequent')
most_frequent_imputer.fit(df_categorical)
df_categorical_mf_imputed = most_frequent_imputer.transform(df_categorical)
print("\n最常见值填充后的类别数据:")
print(pd.DataFrame(df_categorical_mf_imputed, columns=df_categorical.columns))
# --- 固定值填充(例如,针对数值)---
constant_imputer_num = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=0)
constant_imputer_num.fit(df_numeric)
df_numeric_const_imputed = constant_imputer_num.transform(df_numeric)
print("\n固定值 (0) 填充后的数值数据:")
print(pd.DataFrame(df_numeric_const_imputed, columns=df_numeric.columns))
# --- 固定值填充(例如,针对类别)---
constant_imputer_cat = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value='Unknown')
constant_imputer_cat.fit(df_categorical)
df_categorical_const_imputed = constant_imputer_cat.transform(df_categorical)
print("\n固定值 ('Unknown') 填充后的类别数据:")
print(pd.DataFrame(df_categorical_const_imputed, columns=df_categorical.columns))
关于 fit 和 transform 的重要说明: 就像缩放器和编码器一样,填充器必须只在训练数据上拟合。从训练数据中学到的统计量(例如均值、中位数、众数)随后用于转换训练数据和测试数据。这可以防止数据泄露,即测试集中的信息无意中影响预处理步骤。在使用 Scikit-learn Pipeline 中的填充器时,这会自动处理,我们将在稍后介绍。
选择正确的填充策略取决于数据的性质(数值型与类别型)、特征的分布、缺失值的百分比以及您计划使用的机器学习算法的特定要求。尽管 SimpleImputer 涵盖了基本方法,Scikit-learn 也提供了更完善的填充器,例如 KNNImputer(使用 K 近邻算法估计值)和 IterativeImputer(将每个含有缺失值的特征建模为其他特征的函数),这些方法可能带来更精确的结果,但它们的计算成本更高。
这部分内容有帮助吗?
SimpleImputer 以及 KNNImputer 和 IterativeImputer 等更高级的方法。© 2026 ApX Machine Learning用心打造