独热编码One-Hot-Encoding与哑编码dummies、factorize的区别、联系

One-Hot-Encoding与dummies、factorize的区别、联系

  • 独热(onehot)编码基本知识点
  • Pandas中dummies、factorize的用法详解
    • pd.factorize()与哑变量变换pd.get_dummies()相较的优势
    • get_dummies()与factorize()的区别
    • pd.get_dummies()的用法详解
    • pd.factorize()的用法详解
  • sklearn中One-Hot-Encoding的用法详解
    • One-Hot-Encoding与get_dummies的对比

独热(onehot)编码基本知识点

基本概念:
在机器学习的分类任务中,经常存在一个特征有多个分类变量值,例如在kaggle中的Titanic比赛数据中,Embarked的值有S,C,Q。此时,为了进行算法训练,需要 对离散型数据进行onehot编码处理,常见的处理方法有两种

  1. pandas:使用pandas库中的函数pd.dummies()pd.factorize()进行独热编码;
  2. sklearn:使用sklearn库中的OneHotEncoder()方法进行独热编码。

onehot的优点:
1、能够处理非连续型数值特征
2、在一定程度上扩充了特征(例如:性别本身是一个特征,经过one hot编码以后,就变成了男或女两个特征。);
3、将离散特征的取值扩展到了欧式空间(离散特征的某个取值就对应欧式空间的某个点,在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间。);
4、将离散型特征使用one-hot编码,可以让特征之间的距离计算更加合理,相当于做了归一化处理;

Pandas中dummies、factorize的用法详解

pd.factorize()与哑变量变换pd.get_dummies()相较的优势

当一个feature有10几种甚至几百种取值可能的话,使用get_summies是将造成DataFrame的特征列数量激增
例如:feature1取值有[“a”,“b”,…“z”]26中可能的话,显然用哑变量pd.get_dummies() 就将把这一个feature变为26列。明显增加了数据的稀疏性,并且没有意义(视情况而定)。此时使用pd.factorize()会将原特征列分解为0-25种数字。同时1列字符串经过变换后仍是一列,不会造成数据集臃肿。

get_dummies()与factorize()的区别

factorize()对每一个类别映射一个ID,这种映射最后只生成一个特征;
然而,dummy()映射后生成多个特征

pd.get_dummies()的用法详解

核心功能:
为了较方便地对离散型特征进行one-hot编码,即:使用pd.get_dummies( )将定性变量转换为 Dummy 变量仅适用于:出现少数几个独立变量的情形
语法格式:

pandas.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)

参数说明:
data:可以是数组类型,Series类型DataFrame类型
prefix:可以字符串,字符串列表,或字符串的字典类型,默认为None。将data的列名映射到prefix的字符串或者字典;
columns: 指要编码的DataFrame中的列名称list-like类型,默认None。 如果columns=None,则将转换DataFrame中dtype为 objectcategory dtype 的所有列
drop_first:布尔型,默认为False,指是否删除第一列;
典型范例:

import pandas as pd
import numpy as np

#例1:传入series
s=pd.Series(list('abca'))
print(s)
>>>
0    a
1    b
2    c
3    a
dtype: object

s0=pd.get_dummies(s)
print(s0)
>>>
a  b  c
0  1  0  0
1  0  1  0
2  0  0  1
3  1  0  0
#例2:传入DataFrame
df=pd.DataFrame({'A':['a','b','a'],'B':['b','a','c'],
                'C':[1,2,3]})
print(df)
>>>
A  B  C
0  a  b  1
1  b  a  2
2  a  c  3
print(df.info())
>>>
Data columns (total 3 columns):
A    3 non-null object
B    3 non-null object
C    3 non-null int64
dtypes: int64(1), object(2)   
# 默认columns=None,DataFrame中dtype为object或 category dtype的所有列将被转化为demmies类型,其他类型不变。

df0=pd.get_dummies(df,prefix=['col1','col2'])
print(df0)   # C列为int型,故不会被转为dummies类型
>>>
   C  col1_a  col1_b  col2_a  col2_b  col2_c
0  1       1       0       0       1       0
1  2       0       1       1       0       0
2  3       1       0       0       0       1

pd.factorize()的用法详解

核心功能:
使用pandas.factorize( )可以创建一些数字,来表示分类变量(categorical variable)枚举型(enumerated type)变量。具体而言:factorize函数可以将Series中的标称型数据映射称为一组数字,相同的标称型映射为相同的数字。对每一个类别映射一个ID,最后factorize只生成一个特征,不像dummies生成多个特征适用于:出现较多独立变量的情形
语法格式:

pandas.factorize(values, sort=False, order=None, na_sentinel=-1, size_hint=None)

参数说明:
values:sequence(序列类型),一维序列。 在分解之前,不是pandas对象的序列被强制转换为ndarray。
sort:表示是否对unique进行排序。bool类型,默认为False,若sort = True,将对uniques进行排序,并对标签进行洗牌,以便保持关系。
na_sentinel:用于标记“not found”的值。int类型,默认-1;
size_hint:用于提示哈希表sizer。int类型,可选参数;
返回值:包含labelsuniques的两个ndarray,其中,labels为uniques的索引;当values为分类变量时,uniques是唯一的不重复类别标识。
典型范例:

labels,uniques=pd.factorize(['b','b','a','c','b'])  # 不排序
print(labels)
>>>
array([0, 0, 1, 2, 0], dtype=int64)
print(uniques)
>>>
array(['b', 'a', 'c'], dtype=object)

labels,uniques=pd.factorize(['b','b','a','c','b'],sort=True)  # 排序
print(labels)
array([1, 1, 0, 2, 1], dtype=int64)
print(uniques)
array(['a', 'b', 'c'], dtype=object)
#例3
sf_df_last['号码归属省']=pd.factorize(sf_df_last['号码归属省'])[0]  #效果见图1

独热编码One-Hot-Encoding与哑编码dummies、factorize的区别、联系_第1张图片

sklearn中One-Hot-Encoding的用法详解

one-hot是将每个feature的取值个数作为one-hot后的长度,对应的位置0/1的值根据原数据在此位置取值的有/无来确定的,并不是每个feature的max取值的长度编号。如此,可以节约矩阵one-hot后的规模。

import pandas as pd
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import LabelBinarizer
from sklearn.preprocessing import MultiLabelBinarizer

testdata=pd.DataFrame({'pet':['cat','dog','dog','fish'],
                       'age':[4,6,3,3],'salary':[4,5,1,1]})
print(testdata)
>>>
    pet	   age	salary
0	cat  	4	4
1	dog	    6	5
2	dog	    3	1
3	fish	3	1
>>>
#把他们全都二值化,进行 one-hot 编码.
OneHotEncoder(sparse=False).fit_transform(testdata.age)  #报错
>>>ValueError: Expected 2D array, got 1D array instead:
# 从 Warning 信息中得知,原因是 sklearn 的新版本中,OneHotEncoder 的输入必须是 2-D array,而 testdata.age 返回的 Series 本质上是 1-D array,所以要改成 
OneHotEncoder(sparse=False).fit_transform(testdata[['age']])  #正确
# testdata[[‘age’]]的取值是:0,4,6所以对这个三个值进行one-hot化,第一行:[4]===>得到one-hot:[0,1,0]
>>>  
array([[0., 1., 0.],
       [0., 0., 1.],
       [1., 0., 0.],
       [1., 0., 0.]])

可以用同样的方法对 salary 进行 OneHotEncoder, 然后将结果用 numpy.hstack() 把两者拼接起来得到变换后的结果

a1=OneHotEncoder(sparse=False).fit_transform(testdata[['age']])
>>>a1
array([[0., 1., 0.],
       [0., 0., 1.],
       [1., 0., 0.],
       [1., 0., 0.]])
a2=OneHotEncoder(sparse=False).fit_transform(testdata[['salary']])
>>>a2
array([[0., 1., 0.],
       [0., 0., 1.],
       [1., 0., 0.],
       [1., 0., 0.]])
final_ouput=np.hstack((a1,a2))
>>>final_ouput
array([[0., 1., 0., 0., 1., 0.],
       [0., 0., 1., 0., 0., 1.],
       [1., 0., 0., 1., 0., 0.],
       [1., 0., 0., 1., 0., 0.]])

有时候我们除了得到最终编码结果,还想知道结果中哪几列属于 age 的二值化编码,哪几列属于 salary 的,这时候我们可以通过 OneHotEncoder() 自带的 feature_indices_ 来实现这一要求,比如这里 feature_indices_ 的值是[0, 3, 6],表明 第[0:3]列是age的二值化编码,[3:6]是salary的。更多细节请参考 sklearn 文档。

所涉及到的几种 sklearn 的二值化编码函数:OneHotEncoder(), LabelEncoder(), LabelBinarizer(), MultiLabelBinarizer()


One-Hot-Encoding与get_dummies的对比

get_dummies的优势:

  • 1.本身就是 pandas 的模块,所以对 DataFrame 类型兼容性好;
  • 2.无论DataFrame的列是字符型还是数字型都可以进行二值编码;
  • 3.能根据用户指定,自动生成二值编码后的变量名;

get_dummies的劣势:

  • 1.get_dummies 不像 sklearn 的 transformer一样,有 transform方法,所以一旦测试集中出现了训练集未曾出现过的特征取值,简单地对测试集、训练集都用 get_dummies 方法将导致数据错误;
  • 2.get_dummies 得到的结果需要手动输入到 sklearn 里的相应模块;
  • 3.get_dummies 无法像 sklearn 的transformer一样可以输入到pipeline中进行流程化地机器学习过程;

参考链接:
https://blog.csdn.net/wl_ss/article/details/78508500

你可能感兴趣的:(数据分析-pandas,Jupyter,Notebook)