目录
引言
一、数据预处理---处理分类型特征
1、编码
1.1 preprocessing.LabelEncoder 标签专用,将分类转换为分类数值
1.2 preprocessing.OrdinalEncoder 特征专用,将分类特征转换为分类数值
2、独热编码
preprocessing.OneHotEncoder 独热编码,创建哑变量
3、总结
二、处理连续型特征:二值化与分段
1、sklearn.preprocessing.Binarizer 根据阈值将数据二值化
2、preprocessing.KBinsDiscretize
在机器学习中,大多数算法等都只能够处理数值型数据,不能处理文字。在sklearn当中,除了专用来处理文字的算法,其他算法在fit的时候全部要求输入数组或矩阵,也不能够导入文字型数据(其实手写决策树和普斯贝叶斯可以处理文字,但是sklearn中规定必须导入数值型)
然而在现实中,许多标签和特征在数据收集完毕的时候,都不是以数字来表现的:
学历的取值可以是 [“小学”,“初中”,“高中”,“大学”]
付费方式可能包含 [“支付宝”,“现金”,“微信”]
…
在这种情况下,为了让数据适应算法和库,我们必须将数据进行编码,也就是要将文字型数据转换为数值型。
from sklearn.preprocessing import LabelEncoder
y=data.iloc[:,-1]#要输入的是标签,不是特征矩阵,所以允许一维变量
#进行编码
le=LabelEncoder() #实例化
le=le.fit(y) #导入数据
label=le.transform(y) #transform接口调取结果
#label查看获取的结果label
#le.classes_ #属性.classes_查看标签中究竟有多少类别
"""
array(['No', 'Unknown', 'Yes'], dtype=object)
"""
#le.fit_transform(y) #也可以直接fit_transform一步到位,但是不能查看属性class_
#le.inverse_transform(label) #使用inverse_transform可以逆转
data.iloc[:,-1]=label #让标签等于我们运行出来的结果
#data.head()
以上代码可以一步完成
from sklearn.preprocessing import LabelEncoder
data.iloc[:,-1]=LabelEncoder().fit_transform(data.iloc[:,-1])
from sklearn.preprocessing import OrdinalEncoder
data_=data.copy()
#data_.head()
#接口categories_对应LabelEncoder的接口classes_,一模一样的功能
#OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_
data_.iloc[:,1:-1]=OrdinalEncoder().fit_transform(data_.iloc[:,1:-1])
#data_.head()
我们刚才已经用OrdinalEncoder把分类变量Sex和Embarked都转化成数字对应的类别,在舱门Embarked这一列中,我们使用 [0,1,2] 代表了三个不同的舱门,然而这种转换是正确的吗?
我们来思考三种不同性质的分类数据:
1、舱门(S,C,Q)
三种取值S,C,Q是相互独立的,彼此之间完全没有联系,表达的是 S≠C≠Q 的概念。这是名义变量
2、学历(小学,初中,高中)
三种取值不是完全独立的,我们可以明显看出,在性质上可以有高中>初中>小学这样的联系,学历有高低,但是学历取值之间却不是可以计算的,我们不能说小学 + 某个取值 = 初中。这是有序变量
3、体重(>45kg,>90kg,>135kg)
各个取值之间有联系,且是可以互相计算的,比如135kg - 45kg = 90kg,分类之间可以通过数学计算互相转换。这是有距变量。
然而在对特征进行编码的时候,这三种分类数据都会被我们转换为 [0,1,2],这三个数字在算法看来,是连续且可以计算的,这三个数字相互不等,有大小,并且有着可以相加相乘的联系。所以算法会把舱门,学历这样的分类特征,都误会成是体重这样的分类特征。我们把分类转换成数字的时候,忽略了数字中自带的数学性质,所以给算法传达了一些不准确的信息,这会影响我们的建模。
OrdinalEncoder可以用来处理有序变量,但对于名义变量,我们只有使用哑变量的方式来处理,才能够尽量向算法传达最准确的信息:
这样的变化,让算法能够彻底领悟,原来三个取值是没有可计算性质的,是“有你就没有我”的不等概念。在我们的数据中,性别和舱门,都是这样的名义变量。因此我们需要使用独热编码,将两个特征都转换为哑变量。
#data.head()
from sklearn.preprocessing import OneHotEncoder
X=data.iloc[;,1:-1]
enc=OneHotEncoder(categories="auto").fit(X)
result=enc.transform(X).toarry()
#result
#仍然可以一步到位,但为了给大家展示模型属性,上面用了三步
#OneHotEncoder(categories="auto").fit_transform(X).toarray()
#仍然可以还原
#pd.DataFrame(enc.inverse_transform(result))
#enc.get_feature_names()
#result
#result.shape
#axis=1,表示跨行进行合并,也就是将量表左右相连,如果axis=0,就是将量表上下相连
newdata=pa.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()
数据类型以及常用的统计量
根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量。大于阈值的值映射为1,而小于或等于阈值的值映射为0。默认阈值为0时,特征中所有的正值都映射到1。二值化是对文本计数数据的常见操作,分析人员可以决定仅考虑某种现象的存在与否。它还可以用作考虑布尔随机变量的估计器的预处理步骤(例如,使用贝叶斯设置中的伯努利分布建模)。
#将年龄二值化
data_2 = data.copy()
#data_2
from sklearn.preprocessing import Binarizer
X = data_2.iloc[:,0].values.reshape(-1,1) #类为特征专用,所以不能使用一维数组
transformer = Binarizer(threshold=30).fit_transform(X)
#transformer
这是将连续型变量划分为分类变量的类,能够将连续型变量排序后按顺序分箱后编码。
总共包含三个重要参数:
from sklearn.preprocessing import KBinsDiscretizer
X = data.iloc[:,0].values.reshape(-1,1)
est = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
est.fit_transform(X)
#查看转换后分的箱:变成了一列中的三箱
set(est.fit_transform(X).ravel())
est = KBinsDiscretizer(n_bins=3, encode='onehot', strategy='uniform')
#查看转换后分的箱:变成了哑变量
est.fit_transform(X).toarray()