共计 2177 个字符,预计需要花费 6 分钟才能阅读完成。
从电商数据说起:那些让人头疼的数据质量问题
最近接手了一个电商用户行为分析项目,原始数据长这样:
import pandas as pd
df = pd.read_csv('user_behavior.csv')
print(df.head(3))
输出示例:
user_id timestamp behavior_type item_price
0 100230 2023-05-01 08:12 pv NaN
1 NaN 2023-05-01 08:15 fav 89.0
2 100230 2023-05-01 08:15 pv 899.0
- 缺失值:user_id 为空导致无法追踪用户
- 异常值:item_price=899.0 的商品价格明显超出正常范围
- 重复数据:同一用户短时间内重复点击(pv)
数据清洗三板斧
1. 智能处理缺失值
def clean_missing(data: pd.DataFrame) -> pd.DataFrame:
"""处理缺失值的黄金组合"""
# 删除全空列
data.dropna(axis=1, how='all', inplace=True)
# 关键 ID 列用前后值填充
data['user_id'].fillna(method='ffill', inplace=True)
# 数值列用中位数填充
median_price = data['item_price'].median()
data['item_price'].fillna(median_price, inplace=True)
return data
2. 异常值检测与修正
# 使用箱线图法则检测异常值
def detect_outliers(series: pd.Series) -> pd.Series:
Q1 = series.quantile(0.25)
Q3 = series.quantile(0.75)
IQR = Q3 - Q1
return (series < (Q1 - 1.5*IQR)) | (series > (Q3 + 1.5*IQR))
# 修正价格异常
df.loc[detect_outliers(df['item_price']), 'item_price'] = df['item_price'].median()
3. 高效去重策略
# 关键业务字段去重(保留最后一条)df.drop_duplicates(subset=['user_id', 'behavior_type', 'item_id'],
keep='last',
inplace=True
)
特征工程:从原始数据到模型输入
标准化方法选型
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# 适用于有异常值的情况
scaler_std = StandardScaler() # 均值 0, 标准差 1
price_std = scaler_std.fit_transform(df[['item_price']])
# 适用于需要限定范围的特征
scaler_minmax = MinMaxScaler() # 默认缩放到[0,1]
price_norm = scaler_minmax.fit_transform(df[['item_price']])
内存优化技巧
# 查看内存占用
df.info(memory_usage='deep')
# 转换低基数列为 category 类型
df['behavior_type'] = df['behavior_type'].astype('category')
可视化:让数据自己讲故事
专业图表制作
import matplotlib.pyplot as plt
import seaborn as sns
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
# 箱线图 + 散点图组合
plt.figure(figsize=(10,6))
sns.boxplot(x='behavior_type', y='item_price', data=df)
sns.stripplot(
x='behavior_type',
y='item_price',
data=df,
jitter=True,
alpha=0.3
)
plt.title('不同行为类型的商品价格分布')

热力图揭示相关性
# 计算特征相关系数
corr_matrix = df.corr()
# 绘制热力图
sns.heatmap(
corr_matrix,
annot=True,
cmap='coolwarm',
center=0
)
plt.title('特征相关性热力图')
避坑指南:血泪经验总结
- 中文乱码:
- 永久解决方案:修改 matplotlib 配置文件
-
临时方案:
plt.rcParams['font.sans-serif'] = ['SimHei'] -
大数据处理:
- 分块读取:
pd.read_csv(chunksize=100000) -
使用 Dask 替代 Pandas
-
性能优化:
- 避免循环:优先使用向量化操作
- 使用
df.query()替代布尔索引
思考题:向更高级迈进
- 当数据量达到 TB 级时,你认为现有的 Pandas 方案需要做哪些架构调整?
- 如何定量评估不同可视化图表的信息传达效率?是否可以通过 A / B 测试验证?
在实践过程中发现,良好的数据清洗可以节省后续 80% 的调试时间。建议建立自己的数据处理工具库,把常用方法封装成函数。下次遇到类似项目时,你会发现效率真的有显著提升!
正文完
