在Python 数据挖掘中,我们经常使用虚拟变量处理现实问题。那么什么是虚拟变量或者哑变量?本文详细阐释它:
01 数据类型分类
从现实意义上划分,数据类型分为连续型变量与离散型变量。
连续型变量指数值是连续的,比如身高、收入、会员数、课程量等等。每一个变量的值都是连续的。
离散型变量指值是非连续的,比如衣服大小、国籍、省份、性别等。每一个变量的值是不连续的,比如性别只有男与女。
在数据挖掘中,我们经常需要处理离散型变量。为了更方便的使用各种数据挖掘算法,Python引入哑变量。它也叫虚拟变量(dummy variables)、虚设变量、名义变量或离散特征编码,主要解决因变量为离线数据特征变量的情况;也可以理解为分类变量的表示方法。实际上,它并不在数据集中真实存在,而是为了解决离散数据或分类变量而故意添加的变量,也就是根据具有离散特征的列增加新的列。一句话理解,虚拟变量是为解决离散数据而添加原来数据中没有的变量。但是,这并不意味着随意添加变量,应该是根据原来的离散数据进行转换。
离散变量或分类变量转换的规则有两个。第一个是有大小意义的离散数据;第二个是无大小意义的离散数据。
02 有大小意义的离散数据
众所周知,衣服的尺寸有S M L XL XXL等。这种尺寸是具有大小意义的,s小于m;xl小于xxl等。我们可以数值的映射的方法处理,也就是使用连续的数值大小表示此类变量,比如0代表S ;1代表M; 2代表L; 3代表XL; 4代表XXL。这些连续的数值就组成了新的列,比如取名衣服大小。那么衣服大小列就是添加的虚拟变量。
姓名 | 尺码 | 衣服大小 |
Grace | S | 0 |
Kim | L | 2 |
小马哥 | XL | 3 |
Nelson | M | 1 |
SS | XXL | 4 |
xiaoming | L | 2 |
注意:在转换离散数据时,我们尽量不要使用有异常值的情况,比如3000表示XXL。这会给算法训练等带来很大的麻烦。
在Python中,我们使用pandas.Series.map()处理离散特征具有大小意义的数据集。注意map()是对序列中每一个元素进行映射。在使用此方法之前,我们一定要查看数据类型是否为Series.
首先,我们导入数据集,然后选取尺码列为一个序列series,并取名为chima_series。最后,查看其数据类型是pandas.core.series.Series,符合使用map()方法的前提。
补充基础: data['尺码'] 的类型是序列 sereies;data[”尺码“]的类型是数据框dataframe
导入数据
import pandas
data = pandas.read_csv('data.csv')
print(data)
chima_series = data['尺码']
print(type(chima_series))
姓名 性别 尺码
0 Grace female S
1 Kim male L
2 小马哥 male XL
3 Nelson male M
4 SS female XXL
5 xiaoming male L
6 Sanket female M
7 Bill male XL
<class 'pandas.core.series.Series'>
接着,查看数据集中有多少个离散值。我们使用drop_duplicates()方法实现。从结果看出,数据集中有5个离散变量值。
查看尺码离散值
# 查看尺码的离散值,共有五个值
print(chima_series.drop_duplicates())
0 S
1 L
2 XL
3 M
4 XXL
Name: 尺码, dtype: object
最后,我们为每一个尺寸中离散值编码,比如0代表S ;1代表M; 2代表L; 3代表XL; 4代表XXL。然后,我们掉用map()方法实现对数据集中的数据转换,并添加新的列为衣服尺寸。衣服尺寸就是虚拟变量,本来不存在的变量列。如此一来,数据集中,每一行中的尺码后面多了一个表达大小的数字,比如Grace的尺码是s,对应的衣服尺寸数字是0。
转换离散值
# 转换离散值为连续值
chicun = {
'S':0,
'M':1,
'L':2,
'XL':3,
'XXL':4
}
# 调用函数转换 转换
# map是让参数中的数值作用于Series每一个元素的操作。
data['衣服尺寸']= data['尺码'].map(chicun)
print(data)
姓名 性别 尺码 衣服尺寸
0 Grace female S 0
1 Kim male L 2
2 小马哥 male XL 3
3 Nelson male M 1
4 SS female XXL 4
5 xiaoming male L 2
6 Sanket female M 1
7 Bill male XL 3
03 无大小意义的离散数据
有一些离散数据是没有大小意义的,比如性别,只有男女之分。在处理此类变量时,我们会根据变量值的惟一值进行转换,有多少惟一值就转成多少变量。比如男女,只有两个唯一值,我们就在原来的数据集中添加2列,表示虚拟变量。我们可以给它取名为性别-男和性别-女。
在Python中,我们使用方法pandas.get_dummies()处理具有无大小意义的离散数据。具体语法是:
pandas.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)
参数解释: | data : array-like, Series, or DataFrame prefix : string, list of strings, or dict of strings, default None String to append DataFrame column names. Pass a list with length equal to the number of columns when calling get_dummies on a DataFrame. Alternatively, prefixcan be a dictionary mapping column names to prefixes. prefix_sep : string, default ‘_’ If appending prefix, separator/delimiter to use. Or pass a list or dictionary as with prefix. dummy_na : bool, default False Add a column to indicate NaNs, if False NaNs are ignored. columns : list-like, default None Column names in the DataFrame to be encoded. If columns is None then all the columns with object or category dtype will be converted. sparse : bool, default False Whether the dummy columns should be sparse or not. Returns SparseDataFrame if data is a Series or if all columns are included. Otherwise returns a DataFrame with some SparseBlocks. drop_first : bool, default False Whether to get k-1 dummies out of k categorical levels by removing the first level. New in version 0.18.0. dtype : dtype, default np.uint8 Data type for new columns. Only a single dtype is allowed. New in version 0.23.0. |
Returns: | dummies : DataFrame or SparseDataFrame |
首先,我们导入数据集data,然后找到具有离散特征的变量是性别。最后,查看性别列具有多少个惟一值。
导入数据集
import pandas
data = pandas.read_csv('data.csv')
print(data)
gender = data[['性别']]
# 查看有多少离散值
print(‘查看有多少离散值’)
print(gender.drop_duplicates())
姓名 性别 尺码
0 Grace female S
1 Kim male L
2 小马哥 male XL
3 Nelson male M
4 SS NaN XXL
5 xiaoming male L
6 Sanket female M
7 Bill male XL
查看有多少离散值
性别
0 female
1 male
4 NaN
从程序运行结果,我们知道性别列有三个唯一值,分别是female、male、NaN。接着,我们调用pandas.get_dumies进行虚拟化处理。根据该方法的定义,我们首先确定数据集是data, 并在虚拟变量前面添加性别-,然后我们使用dummy_na去除NaN,也就是忽略性别列中的空值。最后,我们得到添加虚拟变量的数据,如下。其中,性别-female与性别-male为添加的虚拟变量。
虚拟化处理
dummise = pandas.get_dummies(
data,
prefix='性别',
columns=['性别'],
dummy_na= False,
# drop_first = True #共生成2个变量,但是该参数 删除第一个变量,保留第二个变量
prefix_sep='-')
print('添加虚拟变量后的数据集是:')
print(dummise)
添加虚拟变量后的数据集是:
姓名 尺码 性别-female 性别-male
0 Grace S 1 0
1 Kim L 0 1
2 小马哥 XL 0 1
3 Nelson M 0 1
4 SS XXL 0 0
5 xiaoming L 0 1
6 Sanket M 1 0
7 Bill XL 0 1
从现实意义讲,Grace的性别是female, 那么肯定不是male。两个虚拟变量表示的意义是重复的,因为我们只需要知道一个虚拟变量的值,即可推断另外一个。比如小马哥的性别是male,对应的虚拟变量 性别-male 为1,而性别-female为0.这种由一列或者几列推到出来的列,则可以去掉,以简化数据集中的列数,进而简化算法的处理。这种被称为共线性。共线性在机器学习或数据挖掘算法中经常被使用到,因大数据时代,数据的列非常多,可以达到几千列。如果再添加虚拟列,数据集可以达到上万列。共线性可以有效解决列过多的问题。
在Python中,我们使用get_dummies()中的参数drop_first实现列的共线性。该参数的意思是删除虚拟变量中的第一个,而保留后面的。这样处理的好处是算法实现简单。
去掉第一个虚拟变量
dummise_drop_first = pandas.get_dummies(
data,
prefix='性别',
columns=['性别'],
dummy_na= False,
drop_first = True,
prefix_sep='-')
# 添加原来的性别列
dummise_drop_first['性别'] = data['性别']
print('去除第一个虚拟变量的数据集是:')
print(dummise_drop_first)
去除第一个虚拟变量的数据集是:
姓名 尺码 性别-male 性别
0 Grace S 0 female
1 Kim L 1 male
2 小马哥 XL 1 male
3 Nelson M 1 male
4 SS XXL 0 NaN
5 xiaoming L 1 male
6 Sanket M 0 female
7 Bill XL 1 male
04 总结
总结。虚拟变量是为了解决离散特征的变量而设计,分为有大小和无大小的两类。它是根据离散的唯一值在数据集中添加新的列。为了简化数据集中列过多,我们使用共线性去掉第一个。