数据分析:数据预处理

 目录

1 缺失值填补

1.1 直接删除法

1.2 使用统计量进行填补

1.2.1 使用pandas进行填补

1.2.2 使用sklearn中的SimpleImputer进行填补

 1.3 使用插值法进行填补

1.3.1 线性插值

1.3.2 多项式插值

1.4 使用算法进行填补

2.重复数据的处理

3.异常值处理

4.数据的无量纲化

 4.1 数据的归一化处理

4.1.1 使用numpy进行归一化处理

4.1.2 使用sklearn.preprocessing.MinMaxScaler进行归一化处理

4.2 数据的标准化处理

4.3 标准化和归一化的选择

5 处理分类型特征

5.1 对于标签进行转化

5.2 对于特征进行转化

5.3 使用独热编码转化为哑变量

6 特征选择

6.1 方差过滤

6.2 相关性过滤

6.2.1 卡方过滤

6.2.2 F检验

6.2.3 互信息法

1 缺失值填补

进行数据预处理的第一步是要检查数据是否含有缺失值,并且需要针对不同情况进行填补或者是删除:

  1. 直接删除:针对数据量非常大并且缺失值较少的数据,可以采取直接删除含有缺失值的行。但如果数据量较少或者缺失值占比较高,直接删除会因为数据量减少影响模型的建立。
  2. 使用统计量进行填补:使用中位数、众数、均值对缺失值进行填补。但会影响数据的分布改变(比如使用均值进行填补会导致数据的方差变小),会导致精度的下降。
  3. 插值法填补:常见的方法有线性插值、样条插值、多项式插值。相较于直接使用统计量进行填补效果较好。
  4. 使用算法填补:使用随机森林算法、回归算法等进行填补。

1.1 直接删除法

import pandas as pd
data.dropna(axis=0,inplace=True)

dropna(axis=0)删除所有有缺失值的行,若改为dropna(axis=1)则表示删除所有有缺失值的列
参数inplace默认值为False,当其为True时表示在原数据集上进行修改,若为False表示生成一个副本,不修改原数据。

1.2 使用统计量进行填补

1.2.1 使用pandas进行填补

以下以“Age”为例使用中位数进行填补,如果要使用众数或均值则分别使用mode、mean来替换median的位置。

#使用fillna直接在dataframe中进行填补
data.loc[:,"Age"] = data.loc[:,"Age"].fillna(data.loc[:,"Age"].median())

1.2.2 使用sklearn中的SimpleImputer进行填补

相比起直接使用pandas进行填补,使用SimpleImputer进行填补相对来说较为麻烦。以下依旧使用“Age”为例进行填补。

from sklearn.impute import SimpleImputer

#sklearn中特征矩阵必须是二维的,将Age转化为二维
Age = data.loc[:,"Age"].values.reshape(-1,1)

#实例化
imp_mean = SimpleImputer()  #默认使用均值进行填补
imp_median = SimpleImputer(strategy='median')  #使用中位数进行填补
imp_frequent = SimpleImputer(strategy='"most_frequent')  #使用众数进行填补
imp_0 = SimpleImputer(strategy='constant',fill_value=0)  #用0进行填补

#训练和导出结果
imp_mean = imp_mean.fit_transform(Age)
imp_median = imp_median.fit_transform(Age)
imp_frequent = imp_frequent。fit_transform(Age)
imp_0 = imp_0.fit_transform(Age)

#以使用中位数为例,填补Age
data.loc[:,"Age"] = imp_median

 SimpleImputer的具体参数如下:

  1. missing_values:确定缺失值的样式,默认值为空值,即np.nan
  2. strategy:采取哪种方式进行缺失值的填补。默认为均值“mean”,其余有使用中位数(median)、众数(most_frequenct)、指定数值或字符(constant,并根据后面fill_value中的值进行填充,fill_value默认为0)。其中均值、中位数只适用于数值型,众数和指定值可以适用于数值型和字符型。
  3. copy:默认为True,此时创建副本,不对原数据进行修改,为False时对原数据进行修改。

 1.3 使用插值法进行填补

并不是每种数据都可以使用插值法进行填补,显然案例中的数据在此处均不适用于插值方法进行填补。

1.3.1 线性插值

可以使用df.interpolate(method='')格式进行线性插值的填补。其中method后来选择依据哪个变量进行插值替换。

1.3.2 多项式插值

多项式插值常使用polyfit()和polyval()函数共同实现,其中polyfit()返回的多项式拟合系数作为polyval()的输入参数,polyval返回插值结果。

使用numpy中的polyfit()函数的基本语法如下: 

np.polyfit(x, y, deg, full=False, w=None)

 其中,

  • x:输入数据
  • y:输入数据
  • deg:用于插值的多项式次数
  • full:是否返回所有信息,为False时返回拟合系数,为True时返回所有信息。

使用numpy中的polyval()函数的基本语法如下:

np.polyval(p,x)

其中,

  • p:由polyfit()计算得到的系数
  • x:要进行插值的点的值

1.4 使用算法进行填补

可以使用随机森林算法对于缺失值进行填补,此处在之后的文章中进行分析学习。

import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt

2.重复数据的处理

处理重复数据的常见方法有:

  1. 直接删除重复数据:如果重复数据为异常数据则直接进行删除,例如身份证号无法重复。若不是,如果数据很大而且缺失值较少,可以直接进行删除,反之会导致数据量减少影响模型
  2. 标记重复数据:新添一列数据,用来标注相同数据出现的数量。

一般的,如果重复数据为异常数据则采取直接删除的处理方式,若不是则可不做处理。

data.drop_duplicates()  #完全相同数据仅保留一个

3.异常值处理

异常值是超出或低于正常范围的数据。对于异常值,可以依据之前的方法对其进行替换或者是直接删除。

常见的处理异常值的方法有:

1. 3\sigma原则

使用3\sigma原则的前提条件是,数据需要服从正态分布,我们可以认为,在三倍的标准差范围外的数据概率极小,可以认为是异常值进行处理。

def z_outliers(data,t=3):
    mean = np.mean(data)
    std = np.std(data)
    outliers = []
    for i in data:
        score = (i-mean)/std
        if abs(score)>t:
            outliers.append(i)
    return outliers

2. 箱型图法

箱型图通常把数据划分为四分位进行处理,令第一个四分位数为q1,第三个四分位数为q3,此时离群点低于q1-1.5*(q3-q1)或高于q3+1.5*(q3-q1)。

def zr_outliers(data):
    q1 = np.percentile(data,25,interpolation = 'midpoint')
    q3 = np.percentile(data,75,interpolation = 'midpoint')
    low = q1-1.5*(q3-q1)
    up = q3+1.5*(q3-q1)
    outliers = []
    for i in data:
        if i < low or i > up:
            outliers.append(i)
    return outliers

4.数据的无量纲化

无量纲化优点:

  1. 加快求解速度:logist回归、SVM、神经网络等
  2. 提高模型精度:K近邻、K-Means

 对于后面即将提到的StandardScaler和MinMaxScaler的fit接口中数组应该至少是二维数组。

 4.1 数据的归一化处理

数据的归一化处理将数据根据极差进行缩放,使所有数据变幻到[0,1]区间内。归一化后的数据服从正态分布,其具体的计算公式如下:

X’ = (X-Xmin) / (Xmax-Xmin)

4.1.1 使用numpy进行归一化处理

import numpy as np

X = np.array(data)
X_nor = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))

若要进行逆转归一化处理(即将归一化的数据还原),只需进行如下的变换:

X_returned = X_nor * (X.max(axis=0) - X.min(axis=0)) + X.min(axis=0)

4.1.2 使用sklearn.preprocessing.MinMaxScaler进行归一化处理

from sklearn.preprocessing import MinMaxScaler
data = [[1, 2], [-1, -2], [3, 4]]

scaler = MinMaxScaler(feature_range=[0,1])  #实例化,feature_range默认即为[0,1],可以不填写
result = scaler.fit_transform(data)  #训练并导出结果

其中,feature_range为将数据压缩到什么范围,默认值为[0,1]。

若要进行逆转归一化处理(即将归一化的数据还原),只需进行如下的变换:

scaler.inverse_transform(result)

4.2 数据的标准化处理

数据标准化可以使数据服从均值为0,方差为1的正态分布。具体计算公式如下所示:

x^{*} = \frac{x- \mu }{\sigma }

在sklearn.preprocessing.StandardScaler中可以实现数据的标准化处理:

from sklearn.preprocessing import StandardScaler
data = [[1, 2], [-1, -2], [3, 4]]

scaler  = StandardScaler()
scaler.fit(data)
x_std = scaler.transform(data)

"""
scaler.var_  #查看方差属性
scaler.mean_ #查看均值属性
x_std.mean()  #均值
x_std.std()  #方差
"""

若要进行逆转归一化处理(即将归一化的数据还原),只需进行如下的变换:

scaler.inverse_transform(x_std)

4.3 标准化和归一化的选择

标准化处理对于异常值非常敏感,在不涉及距离度量、梯度、协方差计算或者需要将数据压缩到一定范围中会选择使用数据的标准化处理。

数据的归一化处理对异常值的敏感性较小,在聚类、支持向量机中经常使用,效果较好。

5 处理分类特征

许多机器学习算法中都只能处理数值型变量,对于文本型变量无法处理。对于文本型分类变量,为了使算法能够处理,我们可以对其进行编码处理,转化为数值型变量。

5.1 对于标签进行转化

from sklearn.preprocessing import LabelEncoder

y = data.iloc[:,-1] #要输入的是标签,不是特征矩阵,所以允许一维

lab = LabelEncoder() #实例化
lab = lab.fit(y) #导入数据
label = lab.transform(y)   #transform接口调取结果

#lab.classes_ #属性.classes_查看标签中究竟有多少类别
#label #查看获取的结果label

#lab.inverse_transform(label) #使用inverse_transform可以逆转

5.2 对于特征进行转化

from sklearn.preprocessing import OrdinalEncoder

OrdinalEncoder().fit(data.iloc[:,1:-1]).categories_
data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data.iloc[:,1:-1])

需要注意的是,特征矩阵的维数至少是2维,如果是一维可以使用reshape进行转换。

5.3 使用独热编码转化为哑变量

由于有时不同的分类之间无法进行简单的算术运算。举个例子,如果进行如上转化,把“苹果”记为0,“葡萄”记为1,“桃子”记为2。三种取值之间可以说是毫无关系的,之间更没有算数运算(加、减、乘、除),如果单纯记为0、1、2,则默认可以进行算数运算了。

所以,对于该种情况,我们可以采用独热编码,将其转变为一个向量,也就是哑变量。

还是上面的例子,经过独热编码处理成哑变量后,可以表示为:

“苹果” [1,0,0];“葡萄” [0,1,0];“桃子” [0,0,1]

from sklearn.preprocessing import OneHotEncoder
X = data.iloc[:,1:-1]
enc = OneHotEncoder(categories='auto').fit(X)
result = enc.transform(X).toarray()

#依然可以还原
pd.DataFrame(enc.inverse_transform(result))

#axis=1,表示跨行进行合并,也就是将量表左右相连,如果是axis=0,就是将量表上下相连
newdata = pd.concat([data,pd.DataFrame(result)],axis=1)
newdata.head()
newdata.drop(["Sex","Embarked"],axis=1,inplace=True)
newdata.columns = ["Age","Survived","Female","Male","Embarked_C","Embarked_Q","Embarked_S"]
newdata.head()

6 特征选择

6.1 方差过滤

如果在一个特征中,大多数的取值都一样,或者是所有均相同,那么此时这个特征对于样本的区分则没有太大的差别,可以认为对于样本没有影响。

例如,要预测明天是晴天、阴天还是下雨,那如果“太阳从那个方向升起”(众所周知,太阳都是从东边升起的)也作为一个特征的话,那这个特征对于预测结果是没有帮助的,需要去除。

通常情况下,进行特征选择,首先要删除方差为0的特征。

from sklearn.feature_selection import VarianceThreshold
selector = VarianceThreshold() #实例化,不填参数默认方差为0
X_var0 = selector.fit_transform(X) #获取删除不合格特征之后的新特征矩阵

VarianceThreshold的默认参数为0,即表示删除方差为0的特征。自定义的数值直接填到括号中即可。

6.2 相关性过滤

选出与标签相关且有意义的特征,如果特征与标签无关,则删除该特征。

6.2.1 卡方过滤

卡方过滤是专门针对分类问题的相关性过滤,会计算每个非负特征和标签之间的卡方统计量,依据卡方统计量由高到低进行排序,取前k个特征,认为后面的特征与标签的相关性较小,去除后面的特征。

如果卡方检验检测到某个特征中所有值均相同,会提示我们先进行方差过滤。

from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

#假设需要300个特征
X_fschi = SelectKBest(chi2, k=300).fit_transform(X_fsvar, y)
X_fschi.shape

卡方过滤有一个很重要的问题,就是如何确定超参数K的取值?

  1. 依旧可以通过画学习曲线的方式来选取K值,但有时候随着K值的不断增加,模型的效果也是越来越好的,无法明确看出具体K值。(所以推荐使用方法2)
  2. 通过p值来判断K值取值。

那么如何通过p值来判断K的取值呢?

卡方检验会返回卡方值和P值两个统计量,对于其返回的p值,我们通常认为,其p值小于0.01或者0.05即为两组数据是相关的,而p值大于0.01或者0.05则认为两组数据是相互独立的。

所以,我们可以根据卡方检验返回的p值,保留p值大于0.05的特征,筛选出去p值小于0.05的特征。

chivalue, pvalues_chi = chi2(X_fsvar,y)
#chivalue #卡方值
#pvalues_chi #p值

k = chivalue.shape[0] - (pvalues_chi > 0.05).sum()
X_fschi = SelectKBest(chi2, k=k).fit_transform(X_fsvar, y)

6.2.2 F检验

F检验又称为齐次性检验,用来捕捉每个特征与标签之间的线性关系的过滤方法。既可以用作回归(feature_selection.f_classif F检验分类),也可以做分类(feature_selection.f_regression F检验回归)。

注意,F检验只能寻找两组数据之间的线性关系!!!

和卡方过滤一样,F检验也需要依靠p值来筛选出相关的特征。同样保留p值大于0.05的特征,筛选出去p值小于0.05的特征。

from sklearn.feature_selection import f_classif
F, pvalues_f = f_classif(X_fsvar,y)
k = F.shape[0] - (pvalues_f > 0.05).sum()
X_fsF = SelectKBest(f_classif, k=k).fit_transform(X_fsvar, y)

6.2.3 互信息法

互信息法可以捕捉特征与标签的线性或者是非线性关系,既可以做分类(feature_selection.mutual_info_classif  互信息分类),也可以做回归(feature_selection.mutual_info_regression  互信息回归)。

互信息法不返回p值或者F值类似的统计量,它返回“每个特征与目标之间的互信息量估计”,这个估计量在[0,1]之间,为0表示两个变量完全独立,为1表示两个变量完全相关。

from sklearn.feature_selection import mutual_info_classif as MIC
result = MIC(X_fsvar,y)
k = result.shape[0] - sum(result <= 0)
X_fsmic = SelectKBest(MIC, k=k).fit_transform(X_fsvar, y)
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值