数据建模的过程中,很多算法无法直接处理非数值型的变量。非数值变量主要分为分类变量和顺序变量。
一、分类变量和顺序变量
分类变量:(性别:男、女)(颜色:红、黄、绿.)
顺序数据:(学历:博士、研究生、学士)(用户价值:高、中、低)
二、运用标志方法处理分类和顺序变量
将所有分类或顺序变量的值域从一列多值的形态转换为多列只包含真值的形态,称为标示法,如下图:
【讨论】为何不能直接用数字来表示不同的分类和顺序数据?
针对分类变量:分类变量各值的价值相等,无论我们用什么值,都无法表达各值相等且带有区分的含义,如下图,1代表男性,0代表女性,存在1的差异。但是实际上二者是不具有差异性的。
针对顺序变量:学历变量的属性值是博士、研究生和学士,可以用3-2-1来表示顺序和排列关系,但是任何一个有序数字的排序都无法准确表达出顺序数据的差异性,因为我们无法得知三个值之间的差异是3-2-1还是30-20-10。
三、利用OneHotEncoder进行分类变量和顺序变量的标志转换
1、生成数据
import pandas as pd
from sklearn.preprocessing import OneHotEncoder #导入OneHotEncoder库
#生成数据
df=pd.DataFrame({'id':[3566841,6541227,3512441],
'sex':['male','female','female'],
'level':['high','low','middle']})
df
输出:
2、python自定义转化过程
#python自定义转换过程
df_new=df.copy()
#循环每一列(变量),判断其数据类型
for col_num,col_name in enumerate(df): #返回列号和列名
col_data=df[col_name] #获取每列数据
col_dtype=col_data.dtype #获取每列数据类型
if col_dtype=='object': #如果是非数值类型
df_new=df_new.drop(col_name,1) #删除df_new当中要进行标志转换的列
values_sets=col_data.unique() #去重分类变量的重复值,得到唯一分类值域
#对每一个分类变量标志操作
for value_unique in values_sets:
col_name_new=col_name+'_'+value_unique #给新表创建新的列名
col_tmp=df.iloc[:,col_num] #获取原始数据列
new_col=(col_tmp==value_unique) #将原始数据列与每个值进行比较,相同为true,否则为false
df_new[col_name_new]=new_col #为最终结果集增加新列值
print(df_new)
输出:
3、使用OneHotEncoder进行标志转换
使用OneHotEncoder进行标志转换时,建议先将分类变量或顺序变量(字符串型等)先处理成int型的数值,如对sex变量,用1代表男性,用2代表女性,再去fit成OntHot编码。
#使用OneHotEncoder进行标志转换
df2=pd.DataFrame({'id':[3566841,6541227,3512441],
'sex':[1,2,2],
'level':[3,1,2]})
id_data=df2['id']
transform_data=df2.values[:,1:] #指定要转化的列
enc=OneHotEncoder() #实例化
df2_new=enc.fit_transform(transform_data).toarray() #标志转换,toarray()保证结果以矩阵方式输出,如果不用,则输出为稀疏矩阵。
df2_all=pd.concat((id_data,pd.DataFrame(df2_new)),axis=1) #合并数据框
df2_all
输出:
与python自定义的标志过程原理其实是一样的,只是输出的列的顺序不同。
虽然列的顺序不同,但不会影响数据建模,只是在得到结果后,可能会导致无法对应到原始特征变量和转换值,不方便特征的解读。