当前位置: 首页 > 后端技术 > Python

一篇文章收集四种变量转换方法!

时间:2023-03-26 14:12:05 Python

在数据集中,通常会遇到两种类型的数据——数值型和分类型。数值变量通常是int和float类型,分类变量是对象类型,也就是我们常说的字符型变量。更正式地说,数值变量称为定量变量,分类变量称为定性变量。数值型变量主要体现为连续值和离散值:连续值:体温、房屋面积等离散值:人数、人数等。我们都知道,在大多数机器学习算法中,都会有更多或与“距离”关系不大,所以只允许传入数值型变量。在不需要其他处理的前提下,可以直接使用原始数据集中的数值型变量。典型的算法有支持向量机、逻辑回归、KNN算法等。当然也有可以处理特征变量的算法,如朴素贝叶斯、决策树、随机森林等。这类模型不关心变量的值,但要注意变量之间的分布和变量之间的条件概率。但是如果要通过sklearn调用这些算法的API,规定还必须传入数值变量才合法。那么这时候,我们通常会面临一个问题,如何将字符型变量转化为数值型变量呢?LabelEncoder我随意建了一个数据集,一共有五个特征和一个类标签。可以看出只有Age和Heat是数值型变量,其余4个是性格(类别)变量。如果想在不调用任何API的情况下将一列字符型数据转换为数值型数据,可以使用自定义函数结合apply或map函数来实现。首先以标签变量Label为例。deflabel(e):ife=='Macho':return0ife=='Beauty':return1else:return2Data["Label"]=Data["Label"].apply(label)这样它对于类别少的特征是可行的,但是如果类别太多,if语句就会吐出来,可观察性极差!在sklearn中,有一个用于处理类别标签的API。只需要索引对应的标签变量,传入即可。fromsklearn.preprocessingimportLabelEncoderLabE=LabelEncoder()#Instantiationlabel=LabE.fit_transform(Data1.iloc[:,-1])Data1.iloc[:,-1]=label#一行代表#Data1.iloc[:,-1]=LabelEncoder().fit_transform(Data1.iloc[:,-1])一行表示就是上面的简化形式,最后的效果是一样的。实例化后,也可以通过对应的方法类获取label变量。LabE.classes_'''array(['male','beauty','beautiful'],dtype=object)'''最终运行结果如下:OrdinalEncoder处理完标签变量后,就是自然要对特征进行处理,至于方法可以选择使用上面提到的自定义函数的方法,但是明显的缺点是每一列都需要一个自定义函数,导致效率低下。sklearn中也有处理features中分类变量的API,用法和上面大致相同:fromsklearn.preprocessingimportOrdinalEncoderData2=Data1.copy()OrE=OrdinalEncoder()#InstantiateData2.iloc[:,2:-1]=OrE.fit_transform(Data2.iloc[:,2:-1])#Data2.iloc[:,2:-1]=OrdinalEncoder().fit_transform(Data2.iloc[:,2:-1])和LabelEncoder最大的区别是OrdinalEncoder要求传入的数据不能是一维的,也就是说如果只想转换一个特征(上面代码是三个),那么需要通过reshape(-1,1)Convertone-dimensionaltoTwo-dimensional重新引入,而LabelEncoder只是针对label变量的,自然接受一维数据。OrdinalEncoder没有class_方法,取而代之的是categories_,也是用来获取传入数据的各个特征的类别。OrE.categories_'''[array(['女性','男性'],dtype=object),array(['优秀','差','好'],dtype=object),array(['>40kg','>50kg','>60kg'],dtype=object)]'''最后运行的结果如下:OneHotEncoder现在我们要考虑一个问题,我们转换变量真的合理吗像这样?上面介绍了数值变量,这里简单说说分类变量。分类变量根据变量之间是否存在顺序关系可以分为无序变量和有序变量,而有序变量可以说是可计算约束下的距离变量:无序变量:数据集性别序变量:数据中的权重sethasdistancevariables:数据集中的成绩首先说明了距离变量。比如上面数据集中的体重有60kg、50kg、40kg三类。很明显这是有序的,但是这三者之间是有可计算关系的,比如60kg-10kg=50kg,类别之间可以通过一定的计算相互转换。以序数变量为例,上述数据集中的成绩也有优、良、差三类。这三类不无关联,因为从某种意义上说,“优”强于“好”、“好”。"强于"差",显然这也是一个有序变量,但这不是一个有距离的变量,因为$excellent-good\neqdifference$是一定的。无序变量很好理解。性别是一个特别典型的例子.类别之间的关系是$male\neqfemale$.这三个类别变量在通过OrdinalEncoder转换的时候,会转换成对应的数字.从算法的角度来说,如果你传给我的数据是一个数字,那么我认为可以相互计算,但是数字有大小,2和0在计算中起着不同的作用。但是我们已经知道,只有距离变量才具有这种相互计算的性质,无序变量和有序变量被误解为距离变量后encoding转换,忽略了数字本身的性质,自然会影响后面的Modeling,而对于这样的变量,可以使用one-hotencoding来将原始变量转换为虚拟变量。fromsklearn.preprocessingimportOneHotEncoderOneHot=OneHotEncoder()#Instantiationresult=OneHot.fit_transform(Data1.iloc[:,2:4]).toarray()OneHotnames=OneHot.get_feature_names().tolist()#获取新特征名称OneHotDf=pd.DataFrame(result,columns=OneHotnames)Data3.drop(columns=['Sex','Grade'],inplace=True)Data3=pd.concat([OneHotDf,Data3],axis=1)最后运行结果如下:这个新的DataFrame的左半部分由很多新的特征组成,每个特征只包含0和1两个元素,其中1表示是,0表示否。例如,Sex特征包含“男”和“女”两个元素,这两个元素可以通过虚拟变量转化为两个新的特征。Sex特征中“male”的样本在新特征“x0_male”中为1,在“x0_female”中为0。反之,可以推导出新特征中“女性”在Sex中的分布。DummyCoding使用OneHotEncoder进行dummy变量转换有点复杂,Pandas库中有相应的方法可以达到同样的效果。Data4=pd.get_dummies(Data4)一行代码比较工整,最终运行结果如下。get_dummies中还有很多参数可以设置,比如新特征的名称。这是对虚拟变量的另一个介绍。虚拟变量与单热编码非常相似。不同之处在于虚拟变量生成的变量比单热编码少一个。下图是虚拟变量的一种形式。转换为虚拟变量后,以Grade这个特征为例,我们可以看到删除了新特征“Grade_good”,因为对于一个人的成绩来说,“优秀”和“差”这两个特征就足够了表达所有信息。如果一个人的成绩不是“优”和“差”,那一定是“好”。因此,one-hot编码后的原始数据是冗余的,虚拟变量被很好地删除了。去除冗余,相应的代价是虚拟变量的表达不如one-hot编码直观。参考链接:[1].https://blog.csdn.net/weixin_...[2].https://www.bilibili.com/video...