在数据分析和机器学习领域,数据标准化是一个关键的预处理步骤。它能够帮助我们消除不同特征之间量纲的影响,确保模型能够公平地对待每个特征,从而提升模型的性能和稳定性。本文将深入探讨如何使用 Python 的 pandas 库进行数据标准化,涵盖各种实用技巧和最佳实践。

一、什么是数据标准化?

数据标准化是指将数据按比例缩放,使之落入一个特定的区间。标准化的核心目标是将不同特征的取值范围统一到相似的尺度上,从而避免模型对数值范围较大的特征产生过度依赖。常见的标准化方法有以下几种:

  1. Min-Max 标准化:将数据缩放到 0 到 1 之间。
  2. Z-Score 标准化:将数据转换为均值为 0,标准差为 1 的分布。
  3. Robust 标准化:使用中位数和四分位数范围进行标准化,对异常值具有较强的鲁棒性。
  4. 单位长度标准化:将每个样本缩放到单位长度(范数为 1)。

二、为什么需要数据标准化?

在实际应用中,不同特征往往具有不同的量纲和取值范围。例如:

  • 身高可能在 150-200 厘米之间
  • 体重可能在 50-100 公斤之间
  • 收入可能在 3000-50000 元之间

如果直接使用这些数据进行分析或建模,模型可能会过度关注数值范围较大的特征(如收入),而忽略了数值范围较小的特征(如身高)。数据标准化可以解决这个问题,让所有特征在模型中具有相同的重要性。

此外,标准化还能带来以下好处:

  • 加速模型收敛:在梯度下降等优化算法中,标准化可以加快收敛速度。
  • 提高模型精度:某些算法(如 KNN、SVM)对特征尺度非常敏感,标准化可以显著提升这些算法的性能。
  • 增强模型稳定性:标准化可以减少异常值对模型的影响。

三、使用 Pandas 实现数据标准化

1. Min-Max 标准化

Min-Max 标准化是最常见的标准化方法之一,它将数据缩放到 0 到 1 之间。公式为:

\(x_{scaled} = \frac{x - x_{min}}{x_{max} - x_{min}}\)

下面是使用 pandas 实现 Min-Max 标准化的代码:

python

运行

import pandas as pd

# 创建示例数据
data = {
    '身高(cm)': [175, 160, 180, 155, 190],
    '体重(kg)': [70, 55, 80, 50, 90],
    '收入(元)': [8000, 5000, 12000, 4000, 20000]
}
df = pd.DataFrame(data)

# 实现Min-Max标准化
def min_max_scaling(column):
    return (column - column.min()) / (column.max() - column.min())

# 对每一列进行标准化
df_scaled = df.apply(min_max_scaling)

print("原始数据:")
print(df)
print("\nMin-Max标准化后的数据:")
print(df_scaled)

2. Z-Score 标准化

Z-Score 标准化将数据转换为均值为 0,标准差为 1 的分布。公式为:

\(x_{scaled} = \frac{x - \mu}{\sigma}\)

其中,\(\mu\)是均值,\(\sigma\)是标准差。

下面是使用 pandas 实现 Z-Score 标准化的代码:

python

运行

import pandas as pd

# 创建示例数据
data = {
    '身高(cm)': [175, 160, 180, 155, 190],
    '体重(kg)': [70, 55, 80, 50, 90],
    '收入(元)': [8000, 5000, 12000, 4000, 20000]
}
df = pd.DataFrame(data)

# 实现Z-Score标准化
def z_score_scaling(column):
    return (column - column.mean()) / column.std()

# 对每一列进行标准化
df_scaled = df.apply(z_score_scaling)

print("原始数据:")
print(df)
print("\nZ-Score标准化后的数据:")
print(df_scaled)

3. Robust 标准化

Robust 标准化使用中位数和四分位数范围进行标准化,对异常值具有较强的鲁棒性。公式为:

\(x_{scaled} = \frac{x - median}{IQR}\)

其中,median是中位数,IQR是四分位数范围(第 75 百分位数与第 25 百分位数的差值)。

下面是使用 pandas 实现 Robust 标准化的代码:

python

运行

import pandas as pd

# 创建示例数据(包含异常值)
data = {
    '身高(cm)': [175, 160, 180, 155, 190, 220],  # 220是异常值
    '体重(kg)': [70, 55, 80, 50, 90, 150],       # 150是异常值
    '收入(元)': [8000, 5000, 12000, 4000, 20000, 100000]  # 100000是异常值
}
df = pd.DataFrame(data)

# 实现Robust标准化
def robust_scaling(column):
    median = column.median()
    q1 = column.quantile(0.25)
    q3 = column.quantile(0.75)
    iqr = q3 - q1
    return (column - median) / iqr

# 对每一列进行标准化
df_scaled = df.apply(robust_scaling)

print("原始数据:")
print(df)
print("\nRobust标准化后的数据:")
print(df_scaled)

四、处理特定列或排除某些列

在实际应用中,我们可能只需要对某些列进行标准化,或者排除某些列不进行标准化。下面是几种常见的处理方法:

1. 只对特定列进行标准化

python

运行

# 只对身高列进行Min-Max标准化
df['身高(cm)_scaled'] = min_max_scaling(df['身高(cm)'])

# 只对体重列进行Z-Score标准化
df['体重(kg)_scaled'] = z_score_scaling(df['体重(kg)'])

# 只对收入列进行Robust标准化
df['收入(元)_scaled'] = robust_scaling(df['收入(元)'])

print(df)

2. 排除某些列不进行标准化

python

运行

# 假设我们有一个包含性别列的数据集,性别列不需要标准化
data = {
    '身高(cm)': [175, 160, 180, 155],
    '体重(kg)': [70, 55, 80, 50],
    '性别': ['男', '女', '男', '女']
}
df = pd.DataFrame(data)

# 选择需要标准化的列(数值列)
numeric_columns = df.select_dtypes(include=['float64', 'int64']).columns

# 对数值列进行Z-Score标准化
df[numeric_columns] = df[numeric_columns].apply(z_score_scaling)

print(df)

3. 使用 for 循环处理多列

python

运行

# 创建示例数据
data = {
    '身高(cm)': [175, 160, 180, 155, 190],
    '体重(kg)': [70, 55, 80, 50, 90],
    '收入(元)': [8000, 5000, 12000, 4000, 20000]
}
df = pd.DataFrame(data)

# 对每一列进行Min-Max标准化,并添加"_scaled"后缀
for column in df.columns:
    df[f'{column}_scaled'] = min_max_scaling(df[column])

print(df)

五、使用 sklearn 进行更高效的标准化

虽然 pandas 可以方便地实现数据标准化,但对于大规模数据集或需要更复杂的标准化方法时,使用 scikit-learn 库会更加高效。下面是使用 sklearn 进行标准化的示例:

python

运行

import pandas as pd
from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler

# 创建示例数据
data = {
    '身高(cm)': [175, 160, 180, 155, 190],
    '体重(kg)': [70, 55, 80, 50, 90],
    '收入(元)': [8000, 5000, 12000, 4000, 20000]
}
df = pd.DataFrame(data)

# 创建Min-Max标准化器
min_max_scaler = MinMaxScaler()

# 创建Z-Score标准化器
standard_scaler = StandardScaler()

# 创建Robust标准化器
robust_scaler = RobustScaler()

# 对数据进行Min-Max标准化
df_min_max = pd.DataFrame(min_max_scaler.fit_transform(df), columns=df.columns)

# 对数据进行Z-Score标准化
df_z_score = pd.DataFrame(standard_scaler.fit_transform(df), columns=df.columns)

# 对数据进行Robust标准化
df_robust = pd.DataFrame(robust_scaler.fit_transform(df), columns=df.columns)

print("Min-Max标准化后的数据:")
print(df_min_max)
print("\nZ-Score标准化后的数据:")
print(df_z_score)
print("\nRobust标准化后的数据:")
print(df_robust)

六、标准化方法的选择指南

在实际应用中,如何选择合适的标准化方法呢?以下是一些参考指南:

标准化方法 适用场景 优点 缺点
Min-Max 标准化 数据分布未知或需要保留数据的原始分布 简单易懂,适合神经网络 对异常值敏感
Z-Score 标准化 数据符合正态分布或需要标准化后的数据具有零均值和单位方差 适合大多数机器学习算法 对异常值敏感
Robust 标准化 数据包含大量异常值 对异常值具有较强的鲁棒性 不适合需要保留数据原始分布的场景
单位长度标准化 用于基于距离的算法(如 KNN、SVM) 保留了数据的方向信息 不适合需要保留数据大小信息的场景

七、常见问题与解决方案

1. 处理包含 NaN 值的数据

python

运行

import pandas as pd
import numpy as np

# 创建包含NaN值的示例数据
data = {
    '身高(cm)': [175, 160, np.nan, 155, 190],
    '体重(kg)': [70, np.nan, 80, 50, 90],
    '收入(元)': [8000, 5000, 12000, np.nan, 20000]
}
df = pd.DataFrame(data)

# 在标准化之前填充NaN值
df_filled = df.fillna(df.mean())  # 使用均值填充

# 对填充后的数据进行Z-Score标准化
df_scaled = df_filled.apply(z_score_scaling)

print("填充后的数据:")
print(df_filled)
print("\n标准化后的数据:")
print(df_scaled)

2. 标准化训练集和测试集

在机器学习中,我们通常需要分别对训练集和测试集进行标准化。需要注意的是,测试集的标准化参数必须来自训练集,以避免数据泄露。

python

运行

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 创建示例数据
data = {
    '身高(cm)': [175, 160, 180, 155, 190, 170, 185, 165],
    '体重(kg)': [70, 55, 80, 50, 90, 65, 85, 60],
    '收入(元)': [8000, 5000, 12000, 4000, 20000, 7000, 15000, 6000]
}
df = pd.DataFrame(data)

# 划分训练集和测试集
X_train, X_test = train_test_split(df, test_size=0.3, random_state=42)

# 创建Z-Score标准化器
scaler = StandardScaler()

# 使用训练集的数据拟合标准化器
scaler.fit(X_train)

# 对训练集和测试集分别进行标准化
X_train_scaled = pd.DataFrame(scaler.transform(X_train), columns=X_train.columns)
X_test_scaled = pd.DataFrame(scaler.transform(X_test), columns=X_test.columns)

print("训练集标准化后的数据:")
print(X_train_scaled)
print("\n测试集标准化后的数据:")
print(X_test_scaled)

八、可视化标准化效果

下面通过可视化来直观地比较不同标准化方法的效果:

python

运行

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler

# 创建示例数据
data = {
    '身高(cm)': [175, 160, 180, 155, 190, 170, 185, 165],
    '体重(kg)': [70, 55, 80, 50, 90, 65, 85, 60],
    '收入(元)': [8000, 5000, 12000, 4000, 20000, 7000, 15000, 6000]
}
df = pd.DataFrame(data)

# 创建标准化器
min_max_scaler = MinMaxScaler()
standard_scaler = StandardScaler()
robust_scaler = RobustScaler()

# 标准化数据
df_min_max = pd.DataFrame(min_max_scaler.fit_transform(df), columns=df.columns)
df_z_score = pd.DataFrame(standard_scaler.fit_transform(df), columns=df.columns)
df_robust = pd.DataFrame(robust_scaler.fit_transform(df), columns=df.columns)

# 设置中文字体
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]

# 创建画布
fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 绘制原始数据
sns.boxplot(data=df, ax=axes[0, 0])
axes[0, 0].set_title('原始数据')

# 绘制Min-Max标准化后的数据
sns.boxplot(data=df_min_max, ax=axes[0, 1])
axes[0, 1].set_title('Min-Max标准化后')

# 绘制Z-Score标准化后的数据
sns.boxplot(data=df_z_score, ax=axes[1, 0])
axes[1, 0].set_title('Z-Score标准化后')

# 绘制Robust标准化后的数据
sns.boxplot(data=df_robust, ax=axes[1, 1])
axes[1, 1].set_title('Robust标准化后')

plt.tight_layout()
plt.show()

九、总结

数据标准化是数据预处理的重要步骤,它能够消除不同特征之间量纲的影响,提高模型的性能和稳定性。本文介绍了四种常见的标准化方法:Min-Max 标准化、Z-Score 标准化、Robust 标准化和单位长度标准化,并展示了如何使用 pandas 和 sklearn 库实现这些方法。

在实际应用中,你可以根据数据的特点和模型的需求选择合适的标准化方法。同时,要注意处理数据中的异常值和缺失值,以及正确地对训练集和测试集进行标准化。

希望本文能够帮助你更好地理解和应用数据标准化技术!

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐