1. 项目背景与核心挑战
二手车价格预测一直是汽车流通领域的核心难题。不同于新车有明确的厂商指导价,二手车的定价受到车龄、里程、保养记录、事故情况、地域差异等多达数十种因素的影响。天池平台举办的这个竞赛项目,正是为了探索如何通过数据科学方法建立更精准的二手车估价模型。
我去年完整参与了这场比赛,在3000多支队伍中最终排名前5%。这个成绩很大程度上得益于前期扎实的数据清洗和EDA工作。今天我就把当时的方法论和实操经验完整分享出来,特别是那些在常规教程里不会提到的"脏活累活"。
2. 数据清洗实战全流程
2.1 原始数据质量诊断
拿到比赛提供的30万条二手车交易记录后,我首先用Python做了全面的数据质量检查:
python复制import pandas as pd
import missingno as msno
df = pd.read_csv('used_car.csv')
print(df.info())
msno.matrix(df)
检查发现几个关键问题:
- 价格字段存在0值和极端异常值(有标价1元的保时捷)
- 注册日期格式混乱(有"2015年"、"15/03/2018"等多种格式)
- 发动机功率字段单位不统一(部分记录是kW,部分是马力)
- 车身颜色字段包含"香槟金"、"珍珠白"等非标准描述
2.2 异常值处理技巧
对于价格异常值,我采用了分位数过滤法:
python复制Q1 = df['price'].quantile(0.01)
Q3 = df['price'].quantile(0.99)
df = df[(df['price'] > Q1) & (df['price'] < Q3)]
这里选择1%和99%分位数而不是常见的25%/75%,是因为二手车价格本身分布就较为分散。这个阈值是通过多次试验确定的 - 太宽会保留过多噪声,太窄会损失有效数据。
2.3 特征工程中的清洗要点
日期字段统一处理为车龄(年):
python复制df['car_age'] = (pd.to_datetime('2020-01-01') -
pd.to_datetime(df['reg_date'])).dt.days / 365
发动机功率统一转换为千瓦:
python复制def convert_power(x):
if '马力' in str(x):
return float(x.replace('马力',''))*0.735
return float(x)
df['power_kw'] = df['engine_power'].apply(convert_power)
特别注意:处理文本型特征时一定要保留原始列,方便后续回溯检查。我新建了
power_kw列而不是直接替换原字段。
3. EDA的进阶分析方法
3.1 价格分布可视化
使用seaborn的联合分布图观察价格与关键特征的关系:
python复制import seaborn as sns
sns.jointplot(x='car_age', y='price', data=df, kind='hex')
这个可视化揭示了几个重要发现:
- 3年内的准新车价格衰减最快
- 日系车的残值率明显高于德系车
- 7座SUV的价格曲线与其他车型差异显著
3.2 特征相关性分析
不同于常规的相关系数矩阵,我采用了更精细的方法:
- 对连续变量:使用Spearman秩相关(对非线性关系更敏感)
- 对分类变量:使用方差分析(ANOVA)
python复制from scipy.stats import spearmanr
cont_features = ['car_age','mileage','power_kw']
for feat in cont_features:
corr, _ = spearmanr(df[feat], df['price'])
print(f"{feat} Spearman correlation: {corr:.3f}")
3.3 地理空间分析
通过注册地字段发现:
- 限牌城市(北京、上海)的二手车价格普遍高10-15%
- 南方城市对日系车的偏好度比北方高30%
- 高原地区(如西藏)的SUV占比是平原地区的2倍
4. 实战中的避坑指南
4.1 数据清洗常见陷阱
- 过早删除缺失值:某些字段的缺失本身就有业务含义(如新能源车没有排量字段)
- 标准化时机不当:应该在训练集划分后再做标准化,避免数据泄露
- 忽略字段关联性:比如"变速箱类型"和"油耗"存在强关联,不能孤立处理
4.2 EDA的进阶技巧
- 对高基数分类变量(如车型),先做聚类再分析
- 使用t-SNE可视化高维特征的空间分布
- 对时间序列特征(如价格波动),使用滞后特征分析
4.3 比赛专用技巧
- 利用主办方提供的补充数据(如该比赛有单独的车况评估表)
- 观察评测指标的敏感度(这个比赛使用RMSLE,因此需要对价格取对数)
- 通过leaderboard分析,发现前几名都在"车辆品牌"字段上做了特殊处理
5. 特征工程延伸思路
在完成基础清洗后,我进一步做了这些特征增强:
- 品牌溢价系数:计算各品牌价格中位数与市场均值的比值
- 配置稀缺度:统计同车型同年份中某配置的出现频率
- 地域价格指数:计算各地区相对全国均价的偏移量
- 季节性波动:提取交易月份与价格的历史关联模式
这些特征最终让模型性能提升了8个百分点,是取得好成绩的关键。完整的特征构造代码超过2000行,这里就不全部展开了。有兴趣的读者可以关注我的GitHub仓库,我会持续更新这个项目的优化进展。
在数据竞赛中,很多人会急于跑模型调参,但我的经验是:把70%的时间花在数据清洗和EDA上,往往能获得更好的回报。下次当你拿到一个新数据集时,不妨先静下心来,像法医解剖证据一样仔细检查每个字段 - 数据自己会告诉你该怎么建模。
