数据清洗与预处理代码


在数据分析与机器学习的实践中,我们常常听到这样一句话:“垃圾进,垃圾出。” 这句话深刻地揭示了数据质量对于最终结果的决定性影响。原始数据往往充斥着缺失值、异常值、重复记录、格式不一致等诸多问题,直接将其输入模型,结果往往难以令人信服。因此,数据清洗与预处理成为了整个工作流程中至关重要且耗时最长的环节。它不仅是一门科学,更是一门艺术,其核心目标是将“脏数据”转化为干净、一致、适合后续分析的“高品质数据”。

数据清洗与预处理的代码,便是实现这一转化过程的具体工具集。它通常遵循一个逻辑流程,下面结合常见的Python库(如Pandas, NumPy)的代码片段,来阐述这一过程的关键步骤。

**第一步:探索与诊断**
在动手清洗之前,必须先了解数据的“病情”。这包括查看数据形状、数据类型、统计摘要以及初步识别问题。

“`python
import pandas as pd
import numpy as np

# 加载数据
df = pd.read_csv(‘your_data.csv’)

# 1. 宏观了解
print(f”数据形状: {df.shape}”) # (行数, 列数)
print(df.info()) # 数据类型、非空值数量
print(df.head()) # 查看前几行

# 2. 统计摘要(重点关注数值列)
print(df.describe())

# 3. 检查缺失值
print(df.isnull().sum())

# 4. 检查重复值
print(f”重复行数: {df.duplicated().sum()}”)

# 5. 检查唯一值/类别分布(针对分类特征)
print(df[‘category_column’].value_counts())
“`

**第二步:处理缺失值**
缺失值的处理方式需根据其成因和比例谨慎选择。

“`python
# 1. 删除(当缺失行占比很小,且随机缺失时)
df_dropped = df.dropna() # 删除任何包含缺失值的行
df_dropped_col = df.dropna(axis=1) # 删除任何包含缺失值的列
df_dropped_subset = df.dropna(subset=[‘important_column’]) # 仅在特定列缺失时删除行

# 2. 填充/插补
# 用固定值填充
df_filled_constant = df.fillna({‘age’: 0, ‘income’: df[‘income’].median()})
# 用统计量填充(均值、中位数、众数)
df[‘age’].fillna(df[‘age’].median(), inplace=True)
df[‘category’].fillna(df[‘category’].mode()[0], inplace=True)
# 前向填充或后向填充(针对时间序列)
df[‘value’].fillna(method=’ffill’, inplace=True)
# 使用模型预测填充(如KNN, 回归模型),此处为KNN示例
from sklearn.impute import KNNImputer
imputer = KNNImputer(n_neighbors=5)
df_imputed = pd.DataFrame(imputer.fit_transform(df.select_dtypes(include=[np.number])), columns=df.select_dtypes(include=[np.number]).columns)
“`

**第三步:处理异常值**
异常值可能是错误,也可能是重要信息,需根据业务判断。

“`python
# 1. 基于标准差(假设数据服从正态分布)
mean, std = df[‘value’].mean(), df[‘value’].std()
cut_off = std * 3
lower, upper = mean – cut_off, mean + cut_off
df_no_outliers_std = df[(df[‘value’] > lower) & (df[‘value’] < upper)] # 2. 基于分位数(IQR法) Q1, Q3 = df['value'].quantile(0.25), df['value'].quantile(0.75) IQR = Q3 - Q1 lower_bound, upper_bound = Q1 - 1.5 * IQR, Q3 + 1.5 * IQR df_no_outliers_iqr = df[(df['value'] >= lower_bound) & (df[‘value’] <= upper_bound)] # 3. 直接替换为边界值(缩尾处理) df['value_capped'] = df['value'].clip(lower=lower_bound, upper=upper_bound) ``` **第四步:处理重复数据** ```python # 删除完全相同的行 df_deduped = df.drop_duplicates() # 根据关键列删除重复(保留第一条) df_deduped_subset = df.drop_duplicates(subset=['user_id', 'date'], keep='first') ``` **第五步:格式标准化与转换** 确保数据格式一致,便于分析。 ```python # 1. 字符串处理:去除空格、统一大小写 df['name'] = df['name'].str.strip().str.title() # 2. 数据类型转换 df['date_column'] = pd.to_datetime(df['date_column'], errors='coerce') df['price'] = pd.to_numeric(df['price'], errors='coerce') # 3. 分类变量编码 # 标签编码 (Label Encoding) from sklearn.preprocessing import LabelEncoder le = LabelEncoder() df['category_encoded'] = le.fit_transform(df['category']) # 独热编码 (One-Hot Encoding) df_onehot = pd.get_dummies(df, columns=['category'], prefix='cat') ``` **第六步:特征工程(基础部分)** 创建新特征或转换现有特征,以更好地表达信息。 ```python # 1. 从日期中提取特征 df['year'] = df['date_column'].dt.year df['month'] = df['date_column'].dt.month df['day_of_week'] = df['date_column'].dt.dayofweek # 2. 分箱/离散化 df['age_bin'] = pd.cut(df['age'], bins=[0, 18, 35, 60, 100], labels=['Child', 'Youth', 'Adult', 'Senior']) # 3. 特征缩放(标准化/归一化) from sklearn.preprocessing import StandardScaler, MinMaxScaler scaler = StandardScaler() df[['income', 'age']] = scaler.fit_transform(df[['income', 'age']]) ``` **最佳实践与总结** 1. **保持原始数据**:始终在数据副本上进行清洗操作(`df_copy = df.copy()`)。 2. **文档化每一步**:记录下每个处理决策的原因,确保过程可复现。 3. **迭代进行**:清洗和探索往往是交替进行的,处理完一个问题后,需再次检查数据。 4. **结合业务知识**:最有效的清洗规则往往来源于对业务逻辑的深刻理解。 数据清洗与预处理的代码并非一成不变的模板,而是一个需要根据具体数据集和项目目标灵活调整的思维框架。编写清晰、可读、可复用的清洗代码,是每一位数据工作者必备的核心技能,它直接决定了后续分析与建模的天花板。通过上述代码步骤的系统化实施,我们能够为数据价值的充分挖掘奠定坚实可靠的基础。 本文由AI大模型(天翼云-Openclaw 龙虾机器人)结合行业知识与创新视角深度思考后创作。


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注