最近开始在天池上做题,进行数据清洗的时候发现 Pandas 的数据透视表是基于MutiIndex的,这是很大一个惊喜,不过发现用起来还是有些问题。比如说iloc
属性没法使用(ix
,iat
估计也一样)。对于爱用 python 进行数据处理的人来说 pandas 真的是天赐宝物。
所以在这里聊聊自己用 pandas 做 Feature Enginering 的一些小体会。
本来做特征工程的主要作用其实是给机器学习使用,提高模型的效率。
由来
这几天空闲时间在做天池的一个竞赛题目,汽车销量预测。(不做另外一个的原因是,主办方在上牌预测中提供的训练数据实在是太少了。需要自行外部获取,我又对行业不了解。所以自然选择了这个)
初见
开头从官网上下载数据的时候就发现了一些问题,比如训练集(train) 数据有多余的列。删除掉之后就继续做了。
把数据简单看下没有大问题的情况下,我一般的习惯是使用 pandas 的pd.DataFrame.describe
和pd.DataFrame.corr
来了解情况。前者是可以看到每一个特征(Feature)的大概情况(见下表格)。而后者则是计算各个特征(Feature)的相关系数(下图是使用Seaborn 进行可视化后的数据)。
sale_date | class_id | sale_quantity | brand_id | compartment | type_id | level_id | department_id | TR | gearbox_type | … | engine_torque | car_length | car_width | car_height | total_quality | equipment_quality | rated_passenger | wheelbase | front_track | rear_track | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 20157.000000 | 20157.000000 | 20157.00000 | 20157.000000 | 20157.000000 | 20157.000000 | 20157 | 20157.000000 | 20157 | 20157 | … | 20157 | 20157.000000 | 20157.000000 | 20157.000000 | 20157.000000 | 20157.000000 | 20157 | 20157.000000 | 20157.000000 | 20157.000000 |
unique | NaN | NaN | NaN | NaN | NaN | NaN | 6 | NaN | 10 | 7 | … | 111 | NaN | NaN | NaN | NaN | NaN | 10 | NaN | NaN | NaN |
top | NaN | NaN | NaN | NaN | NaN | NaN | 1 | NaN | 6 | AT | … | 155 | NaN | NaN | NaN | NaN | NaN | 5 | NaN | NaN | NaN |
freq | NaN | NaN | NaN | NaN | NaN | NaN | 10619 | NaN | 7640 | 8421 | … | 1918 | NaN | NaN | NaN | NaN | NaN | 18238 | NaN | NaN | NaN |
mean | 201490.186784 | 507410.234906 | 126.31205 | 643.293645 | 2.518033 | 1.860297 | NaN | 3.348316 | NaN | NaN | … | NaN | 4577.579600 | 1790.405269 | 1552.624448 | 1876.938582 | 1414.852657 | NaN | 2706.141589 | 1538.063055 | 1538.027980 |
std | 157.488965 | 234920.469728 | 231.13742 | 250.153093 | 0.528447 | 0.608067 | NaN | 1.552570 | NaN | NaN | … | NaN | 266.704254 | 62.189750 | 124.673136 | 222.324373 | 208.956548 | NaN | 129.011827 | 55.662680 | 56.429887 |
min | 201201.000000 | 103507.000000 | 5.00000 | 12.000000 | 1.000000 | 1.000000 | NaN | 1.000000 | NaN | NaN | … | NaN | 3675.000000 | 1510.000000 | 1415.000000 | 1350.000000 | 925.000000 | NaN | 2360.000000 | 1280.000000 | 1290.000000 |
25% | 201402.000000 | 304458.000000 | 16.00000 | 537.000000 | 2.000000 | 2.000000 | NaN | 2.000000 | NaN | NaN | … | NaN | 4431.000000 | 1765.000000 | 1465.000000 | 1720.000000 | 1267.000000 | NaN | 2614.000000 | 1517.000000 | 1515.000000 |
50% | 201506.000000 | 472603.000000 | 47.00000 | 750.000000 | 3.000000 | 2.000000 | NaN | 4.000000 | NaN | NaN | … | NaN | 4598.000000 | 1802.000000 | 1484.000000 | 1835.000000 | 1390.000000 | NaN | 2690.000000 | 1549.000000 | 1550.000000 |
75% | 201609.000000 | 692703.000000 | 142.00000 | 814.000000 | 3.000000 | 2.000000 | NaN | 4.000000 | NaN | NaN | … | NaN | 4718.000000 | 1830.000000 | 1646.000000 | 2020.000000 | 1556.000000 | NaN | 2770.000000 | 1575.000000 | 1571.000000 |
max | 201710.000000 | 978089.000000 | 6284.00000 | 985.000000 | 3.000000 | 4.000000 | NaN | 7.000000 | NaN | NaN | … | NaN | 5266.000000 | 1942.000000 | 1960.000000 | 2520.000000 | 2005.000000 | NaN | 3108.000000 | 1655.000000 | 1671.000000 |
11 rows × 32 columns
corr 计算后使用seaborn可视化。
这里我发现了一个比较有意思的情况,我们要预测的值 sale_quantity 实际上与各项参数的相关系数都不高。看来这个问题确实还需要深挖。
观察各个特征
在观察各项特征(Feature) , 在对数据有了一个简单印象之后,我开始观察各个特征(Feature) 是以那种方式存储(int,float,string)。然后统计了一下各个Feature的一些常见数据。发现了他们基本都是离散的。
在发现数据离散之后我开始逐步去了解数据,逐步发掘各个Feature 与 sale_quantity 之间的数据联系。然后我发现了一个大问题。
发现了问题
主办方提供的数据本身有问题。这个问题需要参赛者观察 训练集 和 要提交的测试集,并且观察完训练集之后才能发现。
那就是——测试集中只提供了车型的 class_id,但是在训练集中,我们可以发现同样的 class_id 中,某几项参数仍然存在不同(level_id
,TR
,gearbox_type
,power
,car_length
,emission_standards_id
,car_height
,total_quality
,equipment_quality
,rated_passenger
,front_track
)。
这也使得我必须要重新清洗数据。
清洗数据
清洗的思路很简单:
- 利用 pandas 把以上几项特征合并起来。
- 再利用
pandas.pivot
数据透视表功能提取出合并特征后的销量数据。 - 选择销量最好的合并特征作为某个 class_id 的实际特征。这样我们就得到了一个车型的特征表(共140种特征)
- 再用车型特征表,重新生成训练集数据和预测集数据。
车型特征表长这样:
|
|
(140, 28)
brand_id_code | compartment_code | type_id_code | department_id_code | displacement_code | if_charging_code | price_level_code | driven_type_id_code | fuel_type_id_code | newenergy_type_id_code | … | TR_code | gearbox_type_code | power_code | car_length_code | emission_standards_id_code | car_height_code | total_quality_code | equipment_quality_code | rated_passenger_code | front_track_code | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
class_id | |||||||||||||||||||||
289403 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 5 | 4 | 217 | 58 | 0 | 71 | 95 | 160 | 2 | 56 |
745137 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 5 | 4 | 210 | 47 | 0 | 42 | 70 | 132 | 2 | 53 |
714860 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 5 | 1 | 11 | 151 | 2 | 26 | 120 | 159 | 2 | 76 |
175962 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 3 | 5 | 186 | 72 | 2 | 30 | 27 | 39 | 2 | 11 |
270690 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 3 | 5 | 190 | 54 | 0 | 146 | 119 | 91 | 2 | 3 |
290854 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 3 | 1 | 74 | 96 | 2 | 115 | 196 | 270 | 2 | 65 |
692703 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 5 | 1 | 25 | 81 | 0 | 110 | 137 | 219 | 2 | 73 |
978089 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 3 | 5 | 184 | 122 | 0 | 31 | 35 | 87 | 2 | 22 |
219195 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 5 | 5 | 21 | 39 | 2 | 121 | 138 | 215 | 2 | 30 |
851857 | 0 | 1 | 0 | 0 | 8 | 0 | 8 | 0 | 1 | 0 | … | 7 | 1 | 110 | 169 | 0 | 113 | 236 | 324 | 2 | 106 |
10 rows × 28 columns
然后就是用清洗好的数据,去重新提取特征和训练就好啦。(这里牵涉到sklearn 的一些模块,以后慢慢写)
最后
对我来说处理特征,主要步骤:
- 初步了解数据概况
-
When you are old
最近访客