数据清洗是数据分析过程中最关键的环节之一,直接影响后续建模和决策的可靠性。本文将深入解析数据清洗的三个核心操作:缺失值填充、重复值剔除和类型转换,并提供完整的Python代码实战示例。
使用pandas
快速定位缺失值:
import pandas as pd
import numpy as np
# 创建示例数据集
data = {
'订单ID': [1001, 1002, 1003, 1004],
'销售额': [1500, np.nan, 1800, 2100],
'客户类型': ['A', 'B', np.nan, 'A'],
'付款日期': ['2025-01-15', '2025-01-17', '2025-01-20', np.nan]
}
df = pd.DataFrame(data)
# 输出缺失值统计
print(df.isnull().sum())
df_drop = df.dropna(axis=0, subset=['销售额'])
df['销售额'].fillna(df['销售额'].median(), inplace=True)
mode = df['客户类型'].mode()[0]
df['客户类型'].fillna(mode, inplace=True)
df['付款日期'] = pd.to_datetime(df['付款日期'])
df['付款日期'].fillna(df['付款日期'].max(), inplace=True)
# 使用KNN算法填充
from sklearn.impute import KNNImputer
imputer = KNNImputer(n_neighbors=2)
df[['销售额']] = imputer.fit_transform(df[['销售额']])
# 标记重复记录(保留首次出现)
df_dup = df[df.duplicated(subset=['订单ID'], keep='first')]
df_clean = df.drop_duplicates()
# 保留最新记录(需搭配时间字段)
df.sort_values('付款日期', ascending=False).drop_duplicates('订单ID')
排序与去重的配合
通过先排序,确保 drop_duplicates 保留的是最关心的数据(如最新日期、最大金额等)。
若省略排序,去重时会随机保留重复项中的某一行(取决于数据原始顺序)。
# 合并重复记录的销售额
df_group = df.groupby('订单ID')['销售额'].sum().reset_index()
[‘销售额’].sum()
对每个分组中的 销售额 列求和,结果是一个 Series(索引为 订单ID,值为对应的总销售额)。
结果如下:
订单ID
1001 1500.0
1002 0.0
1003 1800.0
1004 2100.0
.reset_index()
将分组后的 Series 转换为 DataFrame,并将原来的索引(订单ID)恢复为普通列。
结果如下:
订单ID 销售额
0 1001 1500.0
1 1002 0.0
2 1003 1800.0
3 1004 2100.0
数值存储为字符串
日期格式不统一
分类变量未编码
df['销售额'] = df['销售额'].astype('float64')
df['付款日期'] = pd.to_datetime(df['付款日期'], errors='coerce')
参数说明
参数 | 行为 | 输出列类型 |
---|---|---|
errors='raise' |
遇到无效日期直接抛出异常,程序终止执行 | 未完成转换(保持原类型) |
errors='coerce' |
将无效日期强制转换为 NaT (Not a Time),继续执行 |
datetime64[ns] |
errors='ignore' |
保留原始无效值,但列可能无法转换为日期类型 | object |
# One-Hot编码
df = pd.get_dummies(df, columns=['客户类型'])
# 标签编码
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
df['客户类型'] = le.fit_transform(df['客户类型'])
get_dummies
将 客户类型 这一 分类变量 转换为 虚拟变量(哑变量。
优点
消除类别间的虚假顺序(如"A"和"B"本无序,避免模型误解为数值关系)。
适用于 名义变量(无内在顺序的分类数据),如性别、城市、产品类型。
缺点
若类别数过多(高基数特征),会导致维度爆炸。
def convert_currency(x):
if '$' in str(x):
return float(x.replace('$', ''))
return x
df['销售额'] = df['销售额'].apply(convert_currency)