Untitled (1)

Task2 特征工程

一 特征工程介绍(Feature Engineering)

什么是特征工程?
特征工程解决了什么问题?
为什么特征工程对机器学习很重要?
怎么做特征工程?
怎么做好特征工程?
集众多博友智慧,一文全面了解并应用特征工程。
1 定义及意义
(1)定义

    特征工程(Feature Engineering)特征工程是将原始数据转化成更好的表达问题本质的特征的过程,使得将这些特征运用到预测模型中能提高对不可见数据的模型预测精度。
    特征工程简单讲就是发现对因变量y有明显影响作用的特征,通常称自变量x为特征,特征工程的目的是发现重要特征。
    如何能够分解和聚合原始数据,以更好的表达问题的本质?这是做特征工程的目的。

    “feature engineering is manually designing what the input x’s should be.”
    “you have to turn your inputs into things the algorithm can understand.”

    特征工程是数据挖掘模型开发中最耗时、最重要的一步。

(2)意义

    特征工程是一个包含内容很多的主题,也被认为是成功应用机器学习的一个很重要的环节。如何充分利用数据进行预测建模就是特征工程要解决的问题!

    “实际上,所有机器学习算法的成功取决于如何呈现数据。”
    “特征工程是一个看起来不值得在任何论文或者书籍中被探讨的一个主题。但是他却对机器学习的成功与否起着至关重要的作用。机器学习算法很多都是由于建立一个学习器能够理解的工程化特征而获得成功的。”——ScottLocklin,in “Neglected machine learning ideas”

    数据中的特征对预测的模型和获得的结果有着直接的影响。可以这样认为,特征选择和准备越好,获得的结果也就越好。这是正确的,但也存在误导。预测的结果其实取决于许多相关的属性:比如说能获得的数据、准备好的特征以及模型的选择。

1)特征与属性的区别?

并不是所有的属性都可以看做特征,区分它们的关键在于看这个属性对解决这个问题有没有影响!可以认为特征是对于建模任务有用的属性。
表格式的数据是用行来表示一个实例,列来表示属性和变量。每一个属性可以是一个特征。特征与属性的不同之处在于,特征可以表达更多的跟问题上下文有关的内容。特征是一个对于问题建模有意义的属性。我们使用有意义(有用的)来区别特征和属性,认为如果一个特征没有意义是不会被认为是特征的,如果一个特征对问题没有影响,那就不是这个问题的一部分。在计算机视觉领域,一幅图像是一个对象,但是一个特征可能是图像中的一行;在自然语言处理中每一个文档或者一条微博是一个对象,一个短语或者单词的计数可以作为特征;在语音识别中,一段声音是一个实例,一个特征可能是单个词或者发音。
2)什么是特征重要性?

特征重要性,可以被认为是一个选择特征重要的评价方法。特征可以被分配一个分值,然后按照这个分值排序,那些具有较高得分的特征可以被选出来包含在训练集中,同时剩余的就可以被忽略。特征重要性得分可以帮助我们抽取或者构建新的特征。挑选那些相似但是不同的特征作为有用的特征。
如果一个特征与因变量(被预测的事物)高度相关,那么这个特征可能很重要。相关系数和其他单变量的方法(每一个变量被认为是相互独立的)是比较通用的评估方法。
更复杂的方法是通过预测模型算法来对特征进行评分。这些预测模型内部有这样的特征选择机制,比如MARS,随机森林,梯度提升机。这些模型也可以得出变量的重要性。

2 流程及方法

特征工程的定义形形色色,笔者同样对特征工程的全流程有着自己的理解。下面三幅图是比较常见的特征工程流程,可以参考,便于理解。跟深入了解特征工程,还是需要在广泛学习的基础上对其有充分的自我理解。

    1.图一是基本的数据挖掘场景

在这里插入图片描述

    2.图二是特征工程的迭代过程
    在这里插入图片描述
    3.图三是特征工程的常见方法和步骤 在这里插入图片描述

二 数据获取

要实现特征工程目标,要用到什么数据?需要结合特定业务,具体情况具体分析。
重点考虑如下三方面:
①数据获取途径

    如何获取特征(接口调用or自己清洗or/github资源下载等)
    如何存储?(/data/csv/txt/array/Dataframe//其他常用分布式)

②数据可用性评估

    获取难度
    覆盖率
    准确率

③特征维度
三 数据描述(Feature Describe)

通过数据获取,我们得到未经处理的特征,这时的特征可能有以下问题:

    存在缺失值:缺失值需要补充。
    不属于同一量纲:即特征的规格不一样,不能够放在一起比较。
    信息冗余:对于某些定量特征,其包含的有效信息为区间划分,例如学习成绩,假若只关心“及格”或不“及格”,那么需要将定量的考分,转换成“1”和“0”表示及格和未及格。
    定性特征不能直接使用:某些机器学习算法和模型只能接受定量特征的输入,那么需要将定性特征转换为定量特征。
    信息利用率低:不同的机器学习算法和模型对数据中信息的利用是不同的。

那么最好先对数据的整体情况做一个描述、统计、分析,并且可以尝试相关的可视化操作。主要可分为以下几方面:
1 数据结构
2 质量检验
标准性、唯一性、有效性、正确性、一致性、缺失值、异常值、重复值
3 分布情况
统计值

包括max, min, mean, std等。python中用pandas库序列化数据后,可以得到数据的统计值。
探索性数据分析(EDA,Exploratory Data Analysis)
集中趋势、离中趋势、分布形状
四 特征处理(Feature Processing)

对数据的整体性有一个宏观的了解之后,即需要进入特征工程第一个重要的环节——特征处理,特征处理会消耗大量时间,并且直接影响特征选择的结果。
特征处理主要包括:
①数据预处理。即数据的清洗工作,主要为缺失值、异常值、错误值、数据格式、采样度等问题的处理。
②特征转换。即连续变量、离散变量、时间序列等的转换,便于入模。
1 数据预处理

【特征工程】python特征预处理大全
(1)缺失值处理

有些特征可能因为无法采样或者没有观测值而缺失.例如距离特征,用户可能禁止获取地理位置或者获取地理位置失败,此时需要对这些特征做特殊的处理,赋予一个缺失值。我们在进行模型训练时,不可避免的会遇到类似缺失值的情况,下面整理了几种填充空值的方法
1)缺失值删除(dropna)
①删除实例
②删除特征
2)缺失值填充(fillna)
①用固定值填充

对于特征值缺失的一种常见的方法就是可以用固定值来填充,例如09999-9999, 例如下面对灰度分这个特征缺失值全部填充为-99

data['灰度分'] = data['灰度分'].fillna('-99')

    1

②用均值填充

对于数值型的特征,其缺失值也可以用未缺失数据的均值填充,下面对灰度分这个特征缺失值进行均值填充

data['灰度分'] = data['灰度分'].fillna(data['灰度分'].mean()))

    1

③用众数填充

与均值类似,可以用未缺失数据的众数来填充缺失值

data['灰度分'] = data['灰度分'].fillna(data['灰度分'].mode()))

    1

④用上下数据进行填充

    用前一个数据进行填充

data['灰度分'] = data['灰度分'].fillna(method='pad')

    1

    用后一个数据进行填充

data['灰度分'] = data['灰度分'].fillna(method='bfill')

    1

⑤用插值法填充

data['灰度分'] = data['灰度分'].interpolate()

    1

⑥用KNN进行填充

from fancyimpute import BiScaler, KNN, NuclearNormMinimization, SoftImpute
dataset = KNN(k=3).complete(dataset)

    1
    2

⑦random forest进行填充

from sklearn.ensemble import RandomForestRegressor
zero_columns_2 = ['机构查询数量', '直接联系人数量', '直接联系人在黑名单数量', '间接联系人在黑名单数量',
                '引起黑名单的直接联系人数量', '引起黑名单的直接联系人占比']
#将出现空值的除了预测的列全部取出来,不用于训练                
dataset_list2 = [x for x in dataset if x not in zero_columns_2]
dataset_2 = dataset[dataset_list2]
# 取出灰度分不为空的全部样本进行训练
know = dataset_2[dataset_2['灰度分'].notnull()]
print(know.shape) #26417, 54
# 取出灰度分为空的样本用于填充空值
unknow = dataset_2[dataset_2['灰度分'].isnull()]
print(unknow.shape) #2078, 54
y = ['灰度分']
x = [1]
know_x2 = know.copy()
know_y2 = know.copy()
print(know_y2.shape)
#
know_x2.drop(know_x2.columns[x], axis=1, inplace=True)
print(know_y2.shape)
print(know_x2.shape)
#
know_y2 = know[y]
# RandomForestRegressor
rfr = RandomForestRegressor(random_state=666, n_estimators=2000, n_jobs=-1)
rfr.fit(know_x2, know_y2)
# 填充为空的样本
unknow_x2 = unknow.copy()
unknow_x2.drop(unknow_x2.columns[x], axis=1, inplace=True)
print(unknow_x2.shape) #(2078, 53)
unknow_y2 = rfr.predict(unknow_x2)
unknow_y2 = pd.DataFrame(unknow_y2, columns=['灰度分'])                

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

⑧使用fancyimpute包中的其他方法

# matrix completion using convex optimization to find low-rank solution
# that still matches observed values. Slow!
X_filled_nnm = NuclearNormMinimization().complete(X_incomplete)

    1
    2
    3

# Instead of solving the nuclear norm objective directly, instead
# induce sparsity using singular value thresholding
X_filled_softimpute = SoftImpute().complete(X_incomplete_normalized)

    1
    2
    3

# print mean squared error for the three imputation methods above
nnm_mse = ((X_filled_nnm[missing_mask] - X[missing_mask]) ** 2).mean()
# print mean squared error for the three imputation methods above
nnm_mse = ((X_filled_nnm[missing_mask] - X[missing_mask]) ** 2).mean()
print("Nuclear norm minimization MSE: %f" % nnm_mse)
softImpute_mse = ((X_filled_softimpute[missing_mask] - X[missing_mask]) ** 2).mean()
print("SoftImpute MSE: %f" % softImpute_mse)
knn_mse = ((X_filled_knn[missing_mask] - X[missing_mask]) ** 2).mean()
print("knnImpute MSE: %f" % knn_mse)

    1
    2
    3
    4
    5
    6
    7
    8
    9

⑨缺失值作为数据的一部分不填充

LightGBM和XGBoost都能将NaN作为数据的一部分进行学习,所以不需要处理缺失值。
(2)异常值处理
1)特征异常平滑

    基于统计的异常点检测算法
    例如极差,四分位数间距,均差,标准差等,这种方法适合于挖掘单变量的数值型数据。
    基于距离的异常点检测算法
    主要通过距离方法来检测异常点,将数据集中与大多数点之间距离大于某个阈值的点视为异常点,主要使用的距离度量方法有绝对距离(曼哈顿距离)、欧氏距离和马氏距离等方法。
    基于密度的异常点检测算法
    考察当前点周围密度,可以发现局部异常点。

(3)重复值处理

根据需求判断是否需要去重操作
(4)数据格式处理

    数字类型的转换
    数字单位的调整
    时间格式的处理

(5)数据采样

多的类别过采样/少的类别欠采样来平衡分布欠采样(undersampling)和过采样(oversampling)会对模型带来不一样的影响。
2 特征转换

特征也就是我们常常说的变量/自变量,一般分为三类:

    连续型
    无序类别(离散)型
    有序类别(离散)型

主要转换方式有以下几种:
在这里插入图片描述
(1)连续型特征处理
1)函数转换

有时我们的模型的假设条件是要求自变量或因变量服从某特殊分布(如正太分布),或者说自变量或因变量服从该分布时,模型的表现较好。这个时候我们就需要对特征或因变量进行非线性函数转换。这个方法操作起来很简单,但记得对新加入的特征做归一化。对于特征的转换,需要将转换之后的特征和原特征一起加入训练模型进行训练。
2)特征缩放

某些特征比其他特征具有较大的跨度值。举个例子,将一个人的收入和他的年龄进行比较,更具体的例子,如某些模型(像岭回归)要求你必须将特征值缩放到相同的范围值内。通过缩放可以避免某些特征比其他特征获得大小非常悬殊的权重值。
3)无量纲化

无量纲化使不同规格的数据转换到同一规格。常见的无量纲化方法有标准化、归一化、区间缩放法。标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。区间缩放法利用了边界值信息,将特征的取值区间缩放到某个特点的范围,例如[0, 1]等。
把数据放缩到同样的范围 SVM/NN影响很大 树模型影响小。不是什么时候都需要标准化,比如物理意义非常明确的经纬度,如果标准化,其本身的意义就会丢失。
①标准化
· 均值方差法
· z-score标准化
· StandardScaler标准化

标准化是依照特征矩阵的列处理数据,其通过求z-score的方法,将样本的特征值转换到同一量纲下。标准化需要计算特征的均值和标准差,公式表达为:
在这里插入图片描述
使用preproccessing库的StandardScaler类对数据进行标准化的代码如下:

from sklearn.preprocessing import StandardScaler
#标准化,返回值为标准化后的数据
StandardScaler().fit_transform(iris.data)

    1
    2
    3

②归一化
· 最大最小归一化(最常用)
· 对数函数转换(log)
· 反余切转换

归一化是依照特征矩阵的行处理数据,其目的在于样本向量在点乘运算或其他核函数计算相似性时,拥有统一的标准,也就是说都转化为“单位向量”。规则为l2的归一化公式如下:
在这里插入图片描述
使用preproccessing库的Normalizer类对数据进行归一化的代码如下:

from sklearn.preprocessing import Normalizer
#归一化,返回值为归一化后的数据
Normalizer().fit_transform(iris.data)

    1
    2
    3

③区间缩放法

区间缩放法的思路有多种,常见的一种为利用两个最值进行缩放,公式表达为:
在这里插入图片描述
使用preproccessing库的MinMaxScaler类对数据进行区间缩放的代码如下:

from sklearn.preprocessing import MinMaxScaler
#区间缩放,返回值为缩放到[0, 1]区间的数据
MinMaxScaler().fit_transform(iris.data)
压缩范围
有些分类变量的少部分取值可能占据了90%的case,这种情况下可以采用预测模型、领域专家、或者简单的频率分布统计。具体问题具体分析,高频和低频都是需要特别处理的地方,抛弃效果不好时,可以考虑采样(高频)或上采样(低频),加权等等方法。

    1
    2
    3
    4
    5

4)二值化(定量特征)

特征的二值化处理是将数值型数据输出为布尔类型。其核心在于设定一个阈值,当样本书籍大于该阈值时,输出为1,小于等于该阈值时输出为0。我们通常使用preproccessing库的Binarizer类对数据进行二值化处理。
定量特征二值化的核心在于设定一个阈值,大于阈值的赋值为1,小于等于阈值的赋值为0,公式表达如下:
在这里插入图片描述
使用preproccessing库的Binarizer类对数据进行二值化的代码如下:

from sklearn.preprocessing import Binarizer
 #二值化,阈值设置为3,返回值为二值化后的数据
Binarizer(threshold=3).fit_transform(iris.data)

    1
    2
    3

5)离散化分箱处理(数值型转类别型)

有时候,将数值型属性转换成类别型更有意义,同时将一定范围内的数值划分成确定的块,使算法减少噪声的干扰。
在实际应用中,当你不想让你的模型总是尝试区分值之间是否太近时,分区能够避免过拟合。例如,如果你所感兴趣的是将一个城市作为整体,这时你可以将所有落入该城市的维度值进行整合成一个整体。
分箱也能减小错误的影响,通过将一个给定值划入到最近的块中。
对于一些特殊的模型(信用评分卡)开发,有时候我们需要对连续型的特征(年龄、收入)进行离散化。
常用的离散化方法包括等值划分和等量划分。例如某个特征的取值范围为[010],我们可以将其划分为10段,[0,1),[1,2),,[9,10)

    离散特征的增加和减少都很容易,易于模型的快速迭代;
    稀疏向量内积乘法运算速度快,计算结果方便存储,容易扩展;
    离散化后的特征对异常数据有很强的鲁棒性模型也会更稳定;
    离散化后可以进行特征交叉,由M+N个变量变为M*N个变量,进一步引入非线性 提 升表达能力;
    特征离散化以后,起到了简化了逻辑回归模型的作用,降低了模型过拟合的风险

离散化方法的关键是怎么确定分段中的离散点,下面介绍几种常用的离散化方法:

    等距离离散(等距分组)
    顾名思义,就是离散点选取等距点。
    等样本点离散(等深分组)
    选取的离散点保证落在每段里的样本点数量大致相同
    决策树离散化(最优分组)
    决策树离散化方法通常也是每次离散化一个连续特征,原理如下:
    单独用此特征和目标值y训练一个决策树模型,然后把训练获得的模型内的特征分割点作为离散化的离散点。
    其他离散化方法
    其中,最优分组除决策树方法以外,还可以使用卡方分箱的方法,这种方法在评分卡开发中比较常见。

6)不处理

除了归一化(去中心,方差归一),不用做太多特殊处理,可以直接把连续特征扔到模型里使用。根据模型类型而定。
(2)离散型特征处理
1)数值化处理

二分类问题:能够将类别属性转换成一个标量,最有效的场景应该就是二分类的情况。即{0,1}对应{类别1,类别2}。这种情况下,并不需要排序,并且你可以将属性的值理解成属于类别1或类别2的概率。
多分类问题:选取多分类,编码到[0,classnum)。
类别不平衡问题:样本层面可以采用oversampling/undersampling. 算法层面可以采用代价敏感方法/样本设置权重
也不是所有的无序变量都需要做数值化处理,决策树、随机森林等树模型可能不需要处理,视情况而定。

例:label encoder
一个变量的k个值,按序转换成k个数字(123…k)。例如一个人的状态status有三种取值:bad, normal, good,显然bad < normal < good。这个时候bad, normal, good就可以分别转换成 123。该方法局限性较大:

    不适用于建立预测具体数值的模型,比如线性回归,只能用于分类,
    即使用于分类,也有一些模型不适合,
    可能结果的精度不如one-hot编码。

2)哑编码
①独热编码(one-hot)

例:
再次举一个简单的例子,由{红,绿、蓝}组成的颜色属性,最常用的方式是把每个类别属性转换成二元属性,即从{0,1}取一个值。因此基本上增加的属性等于相应数目的类别。对于数据集中的每个实例,只有一个是1(其他的为0),这也就是独热(one-hot)编码方式(类似于转换成哑变量)。
如果你不了解这个编码的话,你可能会觉得分解会增加没必要的麻烦(因为编码大量的增加了数据集的维度)。相反,你可能会尝试将类别属性转换成一个标量值,例如颜色属性可能会用{1,2,3}表示{红,绿,蓝}。这里存在两个问题,首先,对于一个数学模型,这意味着某种意义上红色和绿色比和蓝色更“相似”(因为|1-3| > |1-2|)。除非你的类别拥有排序的属性(比如铁路线上的站),这样可能会误导你的模型。然后,可能会导致统计指标(比如均值)无意义,更糟糕的情况是,会误导你的模型。还是颜色的例子,假如你的数据集包含相同数量的红色和蓝色的实例,但是没有绿色的,那么颜色的均值可能还是得到2,也就是绿色的意思。

哑编码主要是采用N位状态寄存器来对N个状态进行编码,一个变量N个值就转换成N个虚拟变量,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。
使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对 应欧式空间的某个点。
在回归,分类,聚类等机器等学习算法中,特征之间距离的计算或相似度的计算是 非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算 余弦相似性,基于的就是欧式空间。

优点:
简单,且保证无共线性。
将离散型特征使用one-hot编码,确实会让特征之间的距离计算更加合理。
对离散型特征进行one-hot编码可以加快计算速度。
缺点:太稀(稀疏矩阵)
避免产生稀疏矩阵的常见方法是降维,将变量值较多的分类维度,尽可能降到最少,能降则降,不能降的,别勉强。
②顺序性哑变量

与one-hot编码一样,都是将一个变量的k个值生成k个哑变量,但同时保护了特征的顺序关系。一般的表达方式如下:
在这里插入图片描述
(上面这种表达方式很巧妙地利用递进表达了值之间的顺序关系。)
(3)时间序列处理
1)时间戳处理

时间戳属性通常需要分离成多个维度比如年、月、日、小时、分钟、秒钟。但是在很多的应用中,大量的信息是不需要的。比如在一个监督系统中,尝试利用一个’位置+时间‘的函数预测一个城市的交通故障程度,这个实例中,大部分会受到误导只通过不同的秒数去学习趋势,其实是不合理的。并且维度’年’也不能很好的给模型增加值的变化,我们可能仅仅需要小时、日、月等维度。因此在呈现时间的时候,试着保证你所提供的所有数据是你的模型所需要的。并且别忘了时区,假如你的数据源来自不同的地理数据源,别忘了利用时区将数据标准化。
————————————————
版权声明:本文为CSDN博主「CS正阳」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sunyaowu315/article/details/83782069

常见的特征工程包括:

  1. 异常处理:
    通过箱线图(或 3-Sigma)分析删除异常值;
    BOX-COX 转换(处理有偏分布);
    长尾截断;

  2. 特征归一化/标准化:
    标准化(转换为标准正态分布);
    归一化(抓换到 [0,1] 区间);
    针对幂律分布,可以采用公式:

  3. 数据分桶:
    等频分桶;
    等距分桶;
    Best-KS 分桶(类似利用基尼指数进行二分类);
    卡方分桶;

  4. 缺失值处理:
    不处理(针对类似 XGBoost 等树模型);
    删除(缺失数据太多);
    插值补全,包括均值/中位数/众数/建模预测/多重插补/压缩感知补全/矩阵补全等;
    分箱,缺失值一个箱;

  5. 特征构造:
    构造统计量特征,报告计数、求和、比例、标准差等;
    时间特征,包括相对时间和绝对时间,节假日,双休日等;
    地理信息,包括分箱,分布编码等方法;
    非线性变换,包括 log/ 平方/ 根号等;
    特征组合,特征交叉;
    仁者见仁,智者见智。

  6. 特征筛选
    过滤式(filter):先对数据进行特征选择,然后在训练学习器,常见的方法有 Relief/方差选择发/相关系
    数法/卡方检验法/互信息法;
    包裹式(wrapper):直接把最终将要使用的学习器的性能作为特征子集的评价准则,常见方法有
    LVM(Las Vegas Wrapper) ;
    嵌入式(embedding):结合过滤式和包裹式,学习器训练过程中自动进行了特征选择,常见的有
    lasso 回归;

  7. 降维
    PCA/ LDA/ ICA;
    特征选择也是一种降维。

导入数据
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from operator import itemgetter
train = pd.read_csv('car_train_0110.csv', sep=' ')
test = pd.read_csv('car_testA_0110.csv', sep=' ')
print(train.shape)
print(test.shape)
(250000, 40)
(50000, 39)
train.head()
SaleIDnameregDatemodelbrandbodyTypefuelTypegearboxpowerkilometer...v_14v_15v_16v_17v_18v_19v_20v_21v_22v_23
01348907342016000213.09NaN0.01.0015.0...0.0921390.00000018.763832-1.512063-1.008718-12.100623-0.9470529.0772970.5812143.945923
13066481969732008030772.097.05.01.017315.0...0.0010700.122335-5.685612-0.489963-2.223693-0.226865-0.658246-3.9496214.593618-1.145653
2340675253472002031218.0123.00.01.05012.5...0.0644100.003345-3.2957001.8164993.554439-0.6836750.9714952.625318-0.851922-1.246135
35733253822000061138.087.00.01.05415.0...0.0692310.000000-3.4055211.4978264.7826360.0391011.2276463.040629-0.801854-1.251894
42652351731742003010987.005.05.01.01313.0...0.0000990.001655-4.4754290.1241381.364567-0.319848-1.131568-3.303424-1.998466-1.279368

5 rows × 40 columns

train.columns
Index(['SaleID', 'name', 'regDate', 'model', 'brand', 'bodyType', 'fuelType',
       'gearbox', 'power', 'kilometer', 'notRepairedDamage', 'regionCode',
       'seller', 'offerType', 'creatDate', 'price', 'v_0', 'v_1', 'v_2', 'v_3',
       'v_4', 'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12',
       'v_13', 'v_14', 'v_15', 'v_16', 'v_17', 'v_18', 'v_19', 'v_20', 'v_21',
       'v_22', 'v_23'],
      dtype='object')
test.columns
Index(['SaleID', 'name', 'regDate', 'model', 'brand', 'bodyType', 'fuelType',
       'gearbox', 'power', 'kilometer', 'notRepairedDamage', 'regionCode',
       'seller', 'offerType', 'creatDate', 'v_0', 'v_1', 'v_2', 'v_3', 'v_4',
       'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12', 'v_13',
       'v_14', 'v_15', 'v_16', 'v_17', 'v_18', 'v_19', 'v_20', 'v_21', 'v_22',
       'v_23'],
      dtype='object')

删除异常值

特征构造

#训练集和测试集放在一起 ,方便构造特征
train['train']=1
test['train']=0
data=pd.concat([train,test],ignore_index=True,sort=False)

忽略需要连接的数据框本身的index,当原本的index没有特别意义的时候可以使用,尤其这些数据框的index不完全一致的时候特别有用;

# 使用时间:data['creatDate'] - data['regDate'],反应汽车使用时间,一般来说价格与使用时间成反比
# 不过要注意,数据里有时间出错的格式,所以我们需要 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
# 看一下空数据,有 15k 个样本的时间是有问题的,我们可以选择删除,也可以选择放着。
# 但是这里不建议删除,因为删除缺失数据占总样本量过大,7.5%
# 我们可以先放着,因为如果我们 XGBoost 之类的决策树,其本身就能处理缺失值,所以可以不用管;
data['used_time'].isnull().sum()
30317
# 计算某品牌的销售统计量,同学们还可以计算其他特征的统计量
# 这里要以 train 的数据计算统计量
train_gb = train.groupby("brand")
all_info = {}
for kind, kind_data in train_gb:
info = {}
kind_data = kind_data[kind_data['price'] > 0]
info['brand_amount'] = len(kind_data)
info['brand_price_max'] = kind_data.price.max()
info['brand_price_median'] = kind_data.price.median()
info['brand_price_min'] = kind_data.price.min()
info['brand_price_sum'] = kind_data.price.sum()
info['brand_price_std'] = kind_data.price.std()
info['brand_price_average'] = round(kind_data.price.sum() / (len(kind_data) + 1), 2)
all_info[kind] = info
brand_fe = pd.DataFrame(all_info).T.reset_index().rename(columns={"index": "brand"})
data = data.merge(brand_fe, how='left', on='brand')

数据分桶

# 数据分桶 以 power 为例
# 这时候我们的缺失值也进桶了,

bin = [i*10 for i in range(31)]
data['power_bin'] = pd.cut(data['power'], bin, labels=False)
data[['power_bin', 'power']].head()
# 利用好了,就可以删掉原始数据了
data = data.drop(['creatDate', 'regDate', 'regionCode'], axis=1)
print(data.shape)
data.columns
(300000, 42)





Index(['SaleID', 'name', 'regDate', 'model', 'brand', 'bodyType', 'fuelType',
       'gearbox', 'power', 'kilometer', 'notRepairedDamage', 'regionCode',
       'seller', 'offerType', 'creatDate', 'price', 'v_0', 'v_1', 'v_2', 'v_3',
       'v_4', 'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12',
       'v_13', 'v_14', 'v_15', 'v_16', 'v_17', 'v_18', 'v_19', 'v_20', 'v_21',
       'v_22', 'v_23', 'train', 'used_time'],
      dtype='object')
# 目前的数据其实已经可以给树模型使用了,所以我们导出一下
data.to_csv('data_for_tree.csv', index=0)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值