在数据分析时,会遇到一些非数值型的类别变量,例如字符串类型(string)。比如,西瓜的色泽:青绿、浅白、乌黑等等…直接放在svm、决策树或者贝叶斯分类器时,不方便处理,也直接套用sklearn中的内置算法。因而在预处理时需要对他们做相应的处理。
一般可以把类别数据分为:无序和有序两类。
有序:比如衣服尺码,S、M、L、XL,是有大小的;再比如拥堵指数,数值由0变化到4随拥堵加剧
无序:比如衣服颜色,黑、白、黄、蓝、绿,是没有大小(优劣)序列的类别
(1)有序序列
我们可以用map函数,将字符型类别替换成有大小顺序的数值。
# 定义一个DataFrame数据
data = pd.DataFrame([
["green", "S", 100,"label1"],
["blue", "M", 110,"label2"],
["red", "X", 120,"label3"],
["black", "XL", 130,"label4"]
])
# 设置列名
data.columns = ["color", "size", "price","label"]
#通过枚举获取类标与整数之间的映射关系
label_mapping = {label:idx for idx,label in enumerate(np.unique(data["label"]))}
print(label_mapping)
#对label列进行映射
data["size_label"] = data["label"].map(label_mapping)
print(data)
结果:
(2)无序类别
我们对上面衣服的颜色特征进行编码,将颜色映射为{“green”:0,“blue”:1,“red”:2,“black”:3}。看起来这样映射好像没什么问题,真的没有问题吗?实则不然,我们这样映射实际上给颜色强加了一个大小关系,即black>red>blue>green,实际上颜色是不存在这种关系的,很显然结果肯定也不是最优的。这时,我们可以通过独热编码(one-hot encoding)来解决这一类问题。独热编码是通过创建一个新的虚拟特征,虚拟特征的每一列各代表标称数据的一个值。例如,颜色一共有四个取值green、blue、red、black,独热编码是通过四位二进制来表示,如果是green就表示为[1,0,0,0],对应的颜色是[green,blue,red,black],如果属于哪一种颜色,则取值为1,否则为0。
第一步:先对离散的数字、离散的文本、离散的类别进行编号,使用 LabelEncoder,LabelEncoder会根据取值的种类进行标注。
import sklearn.preprocessing as pre_processing
import numpy as np
label=pre_processing.LabelEncoder()
labels=label.fit_transform(['中国','美国','法国','德国'])
print(labels)
第二步:然后进行独热编码,使用OneHotEncoder
labels=np.array(labels).reshape(len(labels),1) #先将X组织成(sample,feature)的格式
onehot=pre_processing.OneHotEncoder()
onehot_label=onehot.fit_transform(labels)
print(onehot_label.toarray()) #这里一定要进行toarray()
注意:在使用OneHotEncoder进行OneHot编码的时候,需要先将字符串转换成为整数之后才能进行OneHot编码,不然会报错。
也可以通过pandas模块的get_dummies起到同样的作用。
与onehot两者区别是:get_dummies用于对一个数据集处理,而onehot由于提前设定了labelEncoder,所以可以对不同的数据集用同一种转换设定。(我觉得)
# 数据预处理
# 由于色泽、根蒂...都是string,且不可比较大小的变量,调用get_dummyColumns方法进行不可比较大小虚拟变量的转换。
# 以西瓜色泽为例
# (对于可比较大小的虚拟变量,比如‘12个月定存’、‘6个月定存’、‘1个月定存’...)使用Map方法比较虚拟变量的转换
dummyColumns = ['色泽']
'''
for column in dummyColumns:
data[column] = data[column].astype('category')
'''
dummiesData = pd.get_dummies(data,
columns = dummyColumns, prefix=dummyColumns,
prefix_sep = '_', dummy_na=False, drop_first = False)
结果:
参考:
- https://blog.csdn.net/qq_27825451/article/details/83823665
- https://www.cnblogs.com/xitingxie/p/11312045.html