二手车交易价格预测之三-特征工程

1. 导入工具包

import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from operator import itemgetter
%matplotlib inline

2. 数据导入及查看

Train_data = pd.read_csv('used_car_train_20200313.csv', sep=' ')
Test_data = pd.read_csv('used_car_testA_20200313.csv', sep=' ')
print(Train_data.shape)
print(Test_data.shape)

输出:
(150000, 31)
(50000, 30)

  • 查看数据
    二手车交易价格预测之三-特征工程_第1张图片二手车交易价格预测之三-特征工程_第2张图片

3 异常值处理

3.1 删除极限值

def outliers_proc(data, col_name, scale=3):
    """
    用于清洗异常值,默认用 box_plot(scale=3)进行清洗
    :param data: 接收 pandas 数据格式
    :param col_name: pandas 列名
    :param scale: 尺度
    :return:
    """

    def box_plot_outliers(data_ser, box_scale):
        """
        利用箱线图去除异常值
        :param data_ser: 接收 pandas.Series 数据格式
        :param box_scale: 箱线图尺度,
        :return:
        """
        # 求四分位距(IQR)
        iqr = box_scale * (data_ser.quantile(0.75) - data_ser.quantile(0.25))
        # 下外限
        val_low = data_ser.quantile(0.25) - iqr
        # 上外限
        val_up = data_ser.quantile(0.75) + iqr
        # 下极限 bool值
        rule_low = (data_ser < val_low)
        # 上极限 bool值
        rule_up = (data_ser > val_up)
        return (rule_low, rule_up), (val_low, val_up)

    data_n = data.copy()
    data_series = data_n[col_name]
    rule, value = box_plot_outliers(data_series, box_scale=scale)
    #极限值索引
    index = np.arange(data_series.shape[0])[rule[0] | rule[1]]
    print("Delete number is: {}".format(len(index)))
    data_n = data_n.drop(index)
    data_n.reset_index(drop=True, inplace=True)
    print("Now column number is: {}".format(data_n.shape[0]))
    
    #下极限值索引
    index_low = np.arange(data_series.shape[0])[rule[0]]
    outliers = data_series.iloc[index_low]
    print("Description of data less than the lower bound is:")
    print(pd.Series(outliers).describe())
    
    #上极限值索引
    index_up = np.arange(data_series.shape[0])[rule[1]]
    outliers = data_series.iloc[index_up]
    print("Description of data larger than the upper bound is:")
    print(pd.Series(outliers).describe())
    
    #画图
    fig, ax = plt.subplots(1, 2, figsize=(10, 7))
    sns.boxplot(y=data[col_name], data=data, palette="Set1", ax=ax[0])
    sns.boxplot(y=data_n[col_name], data=data_n, palette="Set1", ax=ax[1])
    return data_n

这里以数据“power"特征为例,但是要注意 test 的数据不能删

Train_data = outliers_proc(Train_data, 'power', scale=3)

二手车交易价格预测之三-特征工程_第3张图片

4. 特征构造

4.1 使用时长特征的构造

一辆二手车卖的价格高低,和它使用的时间应该是有关系的,同一个型号的车,理论上来说应该使用时间越少卖的价格越高,使用时间=data[‘creatDate’] - data[‘regDate’],反映汽车的使用时间,一般来说价格与使用时间成反比

# 训练集和测试集放在一起,方便构造特征
Train_data['train']=1
Test_data['train']=0
data = pd.concat([Train_data, Test_data], ignore_index=True)  # 竖着叠加Train_data和Test_data
# 不过要注意,数据里有时间出错的格式,所以我们需要 errors='coerce'
data['used_time'] = (pd.to_datetime(data['creatDate'], format='%Y%m%d', errors='coerce') - 
                            pd.to_datetime(data['regDate'], format='%Y%m%d', errors='coerce')).dt.days  # 增加了一列used_time
#计算缺失值
data['used_time'].isnull().sum()

输出:
15072
查看:
二手车交易价格预测之三-特征工程_第4张图片

4.2 城市特征的构造

# 从邮编中提取城市信息,相当于加入了先验知识
data['city'] = data['regionCode'].apply(lambda x : str(x)[:-3])
data = data

在这里插入图片描述

5. 特征变换

  • 以"power"特征为例:
    二手车交易价格预测之三-特征工程_第5张图片
    现在还有这么奇怪的分布是因为 test 中的 power 极端值 ,对 train 进行极端值处理就正常了
    二手车交易价格预测之三-特征工程_第6张图片对 power 特征取 log,再做归一化
from sklearn import preprocessing
min_max_scaler = preprocessing.MinMaxScaler()
data['power'] = np.log(data['power'] + 1) 
data['power'] = ((data['power'] - np.min(data['power'])) / (np.max(data['power']) - np.min(data['power'])))
data['power'].plot.hist()

二手车交易价格预测之三-特征工程_第7张图片

  • 以 ‘ kilometer’ 为例,直接归一化

二手车交易价格预测之三-特征工程_第8张图片

  • 对其它特征做归一化
# 除此之外 还有我们刚刚构造的统计量特征:
# 'brand_amount', 'brand_price_average', 'brand_price_max',
# 'brand_price_median', 'brand_price_min', 'brand_price_std',
# 'brand_price_sum'
# 这里不再一一举例分析了,直接做变换,
def max_min(x):
    return (x - np.min(x)) / (np.max(x) - np.min(x))

data['brand_amount'] = ((data['brand_amount'] - np.min(data['brand_amount'])) / 
                        (np.max(data['brand_amount']) - np.min(data['brand_amount'])))
data['brand_price_average'] = ((data['brand_price_average'] - np.min(data['brand_price_average'])) / 
                               (np.max(data['brand_price_average']) - np.min(data['brand_price_average'])))
data['brand_price_max'] = ((data['brand_price_max'] - np.min(data['brand_price_max'])) / 
                           (np.max(data['brand_price_max']) - np.min(data['brand_price_max'])))
data['brand_price_median'] = ((data['brand_price_median'] - np.min(data['brand_price_median'])) /
                              (np.max(data['brand_price_median']) - np.min(data['brand_price_median'])))
data['brand_price_min'] = ((data['brand_price_min'] - np.min(data['brand_price_min'])) / 
                           (np.max(data['brand_price_min']) - np.min(data['brand_price_min'])))
data['brand_price_std'] = ((data['brand_price_std'] - np.min(data['brand_price_std'])) / 
                           (np.max(data['brand_price_std']) - np.min(data['brand_price_std'])))
data['brand_price_sum'] = ((data['brand_price_sum'] - np.min(data['brand_price_sum'])) / 
                           (np.max(data['brand_price_sum']) - np.min(data['brand_price_sum'])))
  • 对类别特征进行one encoder
data = pd.get_dummies(data, columns=['model', 'brand', 'bodyType', 'fuelType',
                                     'gearbox', 'notRepairedDamage', 'power_bin'])

你可能感兴趣的:(机器学习,机器学习)