首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python|一文详解数据预处理

Python|一文详解数据预处理

作者头像
数据山谷
发布2020-08-04 14:37:18
2.3K0
发布2020-08-04 14:37:18
举报
文章被收录于专栏:数据山谷数据山谷

数据预处理

通常获取数据通常都是不完整的,缺失值、零值、异常值等情况的出现导致数据的质量大打折扣,而数据预处理技术就是为了让数据具有更高的可用性而产生的,在本文中让我们学习一下如何用Python进行数据预处理。

01

简单的数据预处理

数据预处理是什么

当用户拿到一份新数据的时候,通过各种手段进行数值替换,空值填充等过程就是数据预处理。

本文中我们将会了解到的数据预处理方式有:

① 一般的数据预处理;

② 缺失值的处理;

③ 异常值的处理;

④ 数据变换方法;

⑤ 高级数据预处理方法。

重复数据的处理

数据采集人员在采集数据时,经常会发生采集到重复数据的情况。在Pandas中可以通过最基本的DataFrame创建方法来创造含有重复数据的数据集,进行修改操作。

1)构造一个含有重复数据的数据集,如以下代码所示。

import pandas as pd
# 创建一个带有重复数据的DataFrame
df = pd.DataFrame(data=[['a', 1], ['a', 2], ['a', 3], ['b', 1], ['b', 2],
                        ['a', 1], ['a', 2]],
                  columns=['label', 'num'])
print(df)

运行结果:

 label num
 0   a  1
 1   a  2
 2   a  3
 3   b  1
 4   b  2
 5   a  1
 6   a  2

在运行结果中可以发现7条数据中存在着[‘a’, 1],[‘a’, 2]两组重复数据。

2)Pandas中提供了duplicated()函数用来查找数据集中是否存在重复数据。查找重复数据如以下代码所示。

df = pd.DataFrame(data=[['a', 1], ['a', 2], ['a', 3], ['b', 1], ['b', 2],
                        ['a', 1], ['a', 2]],
                  columns=['label', 'num'])
df = df.duplicated()
print(df)

运行结果:

 0  False
 1  False
 2  False
 3  False
 4  False
 5   True
 6   True
 dtype: bool

其实我们并不需要如此多的运行结果,在判断是否含有重复数据的时候只需要知道“有”或者“没有”就可以了,使用any()函数去判断数据经过duplicated()函数后有没有重复值。

df = pd.DataFrame(data=[['a', 1], ['a', 2], ['a', 3], ['b', 1], ['b', 2],
                        ['a', 1], ['a', 2]],
                  columns=['label', 'num'])
df = any(df.duplicated())
print(df)

运行结果:

True

这样对于数据中是否含有重复值就很容易知道了。

3)对于重复数据,不需要进行改动,只需要进行删除就可以,pandas中提供了drop_duplicates()函数来删除重复数据。处理重复数据如以下代码所示。

df = pd.DataFrame(data=[['a', 1], ['a', 2], ['a', 3], ['b', 1], ['b', 2],
                        ['a', 1], ['a', 2]],
                  columns=['label', 'num'])
df.drop_duplicates(inplace=True)
# df = df.drop_duplicates(inplace=False)
print(df)

运行结果:

 label num
 0   a  1
 1   a  2
 2   a  3
 3   b  1
 4   b  2

在drop_duplicates()函数中,参数inplace=True表示在原数据集上进行操作,参数默认为False。

缺失值的处理

在分析数据的时候往往会遇到很多缺失的数据,该类型的数据严重影响数据分析的结果,本章讲述对于数据中缺失值的处理方法。

  1. 构造一个含有缺失值的数据集。

先创建一个普通的DataFrame,再通过reindex()函数去重构索引,创建出一个带有缺失值的DataFrame,其中(NaN即表示缺失值)如以下代码所示。

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(5, 3),
                  index=['a', 'c', 'd', 'e', 'g'],
                  columns=['1st', '2nd', '3rd'])
# 使用chr()函数创建索引,chr()函数会将转换为ascii码对应的字符
df = df.reindex([chr(x).lower() for x in range(65, 72)])
# df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
print(df)

结果如下:

        1st       2nd       3rd
a -1.083079  1.041412 -0.457510
b       NaN       NaN       NaN
c  1.719107 -0.033295  0.033539
d -1.366099  0.296715  0.416878
e  0.341656  0.332213 -0.620006
f       NaN       NaN       NaN
g -0.677747  0.930917 -0.254245

在Pandas中提供了isnull()函数判断所有位置的元素是否缺失,缺失显示True,不缺失显示False,如以下代码所示。

df = pd.DataFrame(np.random.randn(5, 3),
                  index=['a', 'c', 'd', 'e', 'g'],
                  columns=['1st', '2nd', '3rd'])
df = df.reindex([chr(x).lower() for x in range(65, 72)])
print(df.isnull())
# 数据量较多的时候可以查看前面几行。
# df.isnull().head()

结果如下;

     1st    2nd    3rd
a  False  False  False
b   True   True   True
c  False  False  False
d  False  False  False
e  False  False  False
f   True   True   True
g  False  False  False

在实际的操作中并不需要展示出所有位置的结果,可以结合使用any()函数进行行(列)是否存在空值的判断,如以下代码所示。

df = pd.DataFrame(np.random.randn(5, 3),
                  index=['a', 'c', 'd', 'e', 'g'],
                  columns=['1st', '2nd', '3rd'])
df = df.reindex([chr(x).lower() for x in range(65, 72)])
print(df.isnull().any())

结果如下:

1st  True
2nd  True
3rd  True
dtype: bool

any()函数中可以传入axis参数进行行或列的空值判断,默认为axis=0也就是判断每一列中是否存在空值,axis=1时用于判断行。

如果想要统计每一行或列中含有空值的个数,可在any()函数的后面加入求和函数sum(),如以下代码所示。

df = pd.DataFrame(np.random.randn(5, 3),
                  index=['a', 'c', 'd', 'e', 'g'],
                  columns=['1st', '2nd', '3rd'])
df = df.reindex([chr(x).lower() for x in range(65, 72)])
print(df.isnull().any().sum())

结果如下:

3
  1. 缺失值的填补

缺失值的填补是在进行数据预处理过程中最重要的一环,同样缺失值填补的方法多种多样,需要考虑具体的某一种场景下用怎样的填补方法。

当数据集中出现某一列数据全都为缺失值,或者缺失值的占比很大并且业务上允许删除该属性列的时候。通常大于60%,可以考虑直接删除整列,如以下代码所示。

df = pd.DataFrame(np.random.randn(5, 3),
                  index=['a', 'c', 'd', 'e', 'g'],
                  columns=['1st', '2nd', '3rd'])
df = df.reindex([chr(x).lower() for x in range(65, 72)])
# 以删除2nd列为例
del df['2nd']
print(df)

结果如下:

        1st       3rd
a -0.610682  0.214314
b       NaN       NaN
c  0.121638 -1.589455
d -0.321348 -0.792944
e  1.787892 -1.373090
f       NaN       NaN
g  0.092022  1.086180

对于缺失值而言,只有少数的缺失值时可以直接删掉此行。对于含有大量缺失值的列可以直接进行列删除的处理,如以下代码所示。

df = pd.DataFrame(np.random.randn(5, 3),
                  index=['a', 'c', 'd', 'e', 'g'],
                  columns=['1st', '2nd', '3rd'])
df = df.reindex([chr(x).lower() for x in range(65, 72)])
# dropna中提供了参数axis,其中0代表行,1代表列
df = df.dropna(axis=0)
print(df)

del方法和dropna()函数在删除列区别在于,del删除指定列,dropna删除含有缺失值的所有列。

结果如下:

        1st       2nd       3rd
a -0.001636 -0.462246 -0.630965
c -0.834343 -0.026846 -0.206404
d -0.924094  1.343112  2.162887
e  2.534455  1.207891 -0.801314
g -0.374566  0.904248  1.088779

指定数据填补缺失值,使用标量0来替换缺失值在很多情况下都会用0来填充缺失值,比如对于一列表示婚龄的数据,若有很多缺失值,可以认为没有数据的是因为未结婚的人群无法选择一样,此时就可以用0来表示没结婚的人群的婚龄。

Pandas中的fillna()函数提供了填充缺失值的方法,该方法中不仅可以填充数值数据,也可以进行字符串的填充,如以下代码所示。

df = pd.DataFrame(np.random.randn(5, 3),
                  index=['a', 'c', 'd', 'e', 'g'],
                  columns=['1st', '2nd', '3rd'])
df = df.reindex([chr(x).lower() for x in range(65, 72)])
# dropna中提供了参数axis,其中0代表行,1代表列
df = df.fillna(0)
print(df)

结果如下:

        1st       2nd       3rd
a -0.073320 -1.040557  0.625403
b  0.000000  0.000000  0.000000
c  0.259383  0.623854 -1.012501
d -0.929179 -0.071979  0.036534
e  0.454091 -0.940268 -0.130758
f  0.000000  0.000000  0.000000
g  0.808844  1.888317  1.410490

数值型数据填充方式:当缺失值为数值型时,通常用均值来进行填补。pandas中提供了mean()函数去计算均值,在用均值填补缺失值的时候需要去判断每一列的数据类型,如以下代码所示。

df = pd.DataFrame(np.random.randn(5, 3),
                  index=['a', 'c', 'd', 'e', 'g'],
                  columns=['1st', '2nd', '3rd'])
df = df.reindex([chr(x).lower() for x in range(65, 72)])
# dropna中提供了参数axis,其中0代表行,1代表列
df['2nd'] = df['2nd'].fillna(df['2nd'].mean())
print(df)

结果如下:

        1st       2nd       3rd
a  0.245117  0.472671  0.099662
b       NaN -0.353180       NaN
c -0.392289 -0.705262 -2.850869
d  1.444145  0.648115 -1.110650
e  0.969916 -1.198083  1.078948
f       NaN -0.353180       NaN
g  0.339332 -0.983339 -1.598624

当缺失值所在的变量为数值型时,对于中位数填充只需要把均值填充, mean()函数改成median()函数即可用中位数来填补数据,如以下代码所示。

df = pd.DataFrame(np.random.randn(5, 3),
                  index=['a', 'c', 'd', 'e', 'g'],
                  columns=['1st', '2nd', '3rd'])
df = df.reindex([chr(x).lower() for x in range(65, 72)])
# dropna中提供了参数axis,其中0代表行,1代表列
df['2nd'] = df['2nd'].fillna(df['2nd'].median())
print(df)

结果如下:

        1st       2nd       3rd
a -1.478387 -0.392058  1.079640
b       NaN -0.392058       NaN
c -1.357133 -0.431554 -1.451272
d  0.255212  0.392723  0.035754
e -0.999840 -0.253316  1.549664
f       NaN -0.392058       NaN
g -1.258107 -1.468062 -1.773574

字符型数据填充方式:当缺失值为字符型数据时,通常用众数填充缺失值。pandas中的mode()函数来使用众数填补缺失值,如以下代码所示。

import pandas as pd
import numpy as np
import random
# 使用随机的方法创建一个字符型的DataFrame
df = pd.DataFrame(
    [random.choice(['apple', 'banana', 'orange', 'pear']) for i in range(15)])
# 转换DataFrame的形状为5*3
df = pd.DataFrame(df.values.reshape(5, 3))
df.index = ['a', 'c', 'd', 'e', 'g']
df.columns = ['1st', '2nd', '3rd']
df = df.reindex([chr(x).lower() for x in range(65, 72)])
# 使用众数来填充数据
df['2nd'] = df['2nd'].fillna(df['2nd'].mode()[0])
print(df)

结果如下:

      1st     2nd     3rd
a    pear    pear  banana
b     NaN  banana     NaN
c  banana  banana   apple
d  banana  orange  banana
e  orange  orange  orange
f     NaN  banana     NaN
g  orange  banana  banana

random中的choice()函数去随机选择一些字符型数据生成一个DataFrame,再转换DataFrame的形状为5*3,最后使用pandas中的mode()函数来使用众数填补缺失值。其中mode()[0]表示在存在多种众数的情况下选取第一个值。

在Python中还提供了根据上(下)一条数据的值对缺失值进行填充,对于这种方式,只需要更改fillna()中的参数即可,如以下代码所示。

df = pd.DataFrame(np.random.randn(5, 3),
          index=['a', 'c', 'd', 'e', 'g'],
          columns=['1st', '2nd', '3rd'])
df = df.reindex([chr(x).lower() for x in range(65, 72)])
# method参数为'pad'时,按照上一行进行填充
# method参数为'bfill'时,按照下一行进行填充
df= df.fillna(method='pad')
print(df)

结果如下:

        1st       2nd       3rd
a -0.530551 -0.676573  1.140592
b -0.530551 -0.676573  1.140592
c -1.610111  1.253288 -0.174413
d -0.572878  0.771014  1.245265
e -0.078281 -0.348678  1.917448
f -0.078281 -0.348678  1.917448
g -0.579313 -0.909112  1.723621

异常值的处理

在异常值处理之前需要对异常值进行识别,一般多采用单变量散点图或是箱线图来达到异常值进行识别目的,利用图形来判断数值是否处于正常范围。

  1. 绘制箱线图查看异常值

箱线图中含有上边缘和下边缘,如果有数据点超出了上下边缘,就会把该类数据点看作是异常值,箱线图中包含内容如下图所示。

箱线属性描述:

① 上四分位数(Q3):75%位置的数据值;

② 下四分位数(Q1):25%位置的数据值;

③ 四分位距: Q=Q3-Q1;

④ 上边缘:Q3+1.5 Q;

⑤ 下边缘:Q1-1.5 Q。

示例1:通过具体数据来通过箱线图查看缺失值。随机生成数据, 对于不同性别、不同年龄的特征(girl_20、boy_20、girl_30、boy_30)来表示男生、女生在20岁和30岁时的收入分布。随机创造70-100个符合正态分布的数据,绘制出对应的箱线图,如以下代码所示。

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()  # 子图


# 封装一下这个函数,用来后面生成数据
def list_generator(mean, dis, number):
    # normal分布,输入的参数是均值、标准差以及生成的数量
    return np.random.normal(mean, dis * dis, number)


# 生成四组数据用来做实验,数据量都为50
# 分别代表男生、女生在20岁和30岁的收入分布
girl_20 = list_generator(1000, 10.5, 50)
boy_20 = list_generator(1500, 20.5, 50)
girl_30 = list_generator(3000, 25.1056, 50)
boy_30 = list_generator(5000, 29.54, 50)
data = [girl_20, boy_20, girl_30, boy_30]
# 用positions参数设置各箱线图的位置
ax.boxplot(data, positions=[
    0,
    0.6,
    3,
    3.7,
])
# 设置x轴刻度标签
ax.set_xticklabels([
    "girl20",
    "boy20",
    "girl30",
    "boy30",
])
plt.show()

运行结果样式如下图所示:

girl20和boy20两个属性中出现了在箱线图之外的圆圈,这就是这两个属性所存在的异常值。

  1. 异常值的处理方法

异常值处理方法:① 删除含有异常值的记录;② 视为缺失值来处理;③ 不处理。

根据指定数据的删除方法以及缺失值的处理方法,深入学习异常值转换成缺失值。

1)计算上边缘和下边缘

判断一下该列的上边缘和下边缘,如以下代码所示。

import numpy as np
import pandas as pd


# 封装一下这个函数,用来后面生成数据
def list_generator(mean, dis, number):
    # normal分布,输入的参数是均值、标准差以及生成的数量
    return np.random.normal(mean, dis * dis, number)


# 生成四组数据用来做实验,数据量都为50
# 分别代表男生、女生在20岁和30岁的收入分布
girl_20 = list_generator(1000, 10.5, 50)
boy_20 = list_generator(1500, 20.5, 50)
girl_30 = list_generator(3000, 25.1056, 50)
boy_30 = list_generator(5000, 29.54, 50)
data = [girl_20, boy_20, girl_30, boy_30]
df = pd.DataFrame({
    'girl20': girl_20,
    'boy20': boy_20,
    'girl30': girl_30,
    'boy30': boy_30
})
s = df.describe()
print(s)
print('-' * 50)
# 基本统计量
q1 = s.loc['25%'][0]
q3 = s.loc['75%'][0]
iqr = q3 - q1
mi = q1 - 1.5 * iqr
ma = q3 + 1.5 * iqr
print('分位差为:%.3f,下限为:%.3f,上限为:%.3f' % (iqr, mi, ma))

运行结果:

            girl20        boy20       girl30        boy30
count    50.000000    50.000000    50.000000    50.000000
mean    986.506573  1407.044007  3071.759102  4830.613134
std     101.910800   378.120218   618.421610   753.990111
min     692.472224   661.495150  1284.628225  2950.875322
25%     921.181027  1217.701326  2656.324485  4288.638289
50%     994.044804  1374.945995  3020.741556  4945.984804
75%    1056.785261  1553.945982  3351.613151  5306.243930
max    1213.199964  2802.276364  4447.697361  6257.073997
--------------------------------------------------
分位差为:135.604,下限为:717.775,上限为:1260.192

在panndas中提供了describe()函数去查看基本的统计量,只需提取出gril20列对应的25%分位数和75%分位数即可,提取之后计算对应的上边缘和下边缘。

2)判断异常值并转换为缺失值

先使用筛选条件来找到异常值,如以下代码所示。

error = df[(df['girl20'] < mi) | (df['girl20'] > ma)]
print(error)
print('异常值共%i条' % len(error))

结果如下:

       girl20        boy20       girl30        boy30
8  692.472224  2802.276364  2323.241344  4162.719777
异常值共1条

使用了pandas中的mask函数替换数据中2条异常值。该函数能够满足过滤条件的数据替换成想要的结果,以下代码所示。

df['girl20'] = df['girl20'].mask((df['girl20'] < mi) | (df['girl20'] > ma),
                                 None)
print(df.loc[4])
print(df.loc[39])

结果如下:

girl20    853.304
boy20     1694.83
girl30    2582.11
boy30     5234.39
Name: 4, dtype: object
girl20    1092.92
boy20     1314.35
girl30    2691.67
boy30     5815.37
Name: 39, dtype: object

把异常值全部转换为缺失值时,可以使用缺失值填补的方法进行数据的填补。

02

数据变换

一份完整的数据,数据上虽然没有缺失值,但是有一些数据并不是用户需要的形式,如字符型数据、数据间差异较大的数据等等,处理这些数据需要进行数据变换。

数据变换方法:数据类型转换,数据标准化处理(Z-score标准化),数据归一化处理(Min-Max标准化)。

数据归一化:数据归一化会将所有的数据约束到[0,1]的范围内。

转换数据类型

pandas中提供了map函数用于数据转换,通常将一些字符型数据转换为可以用于计算机计算的数值型数据。

示例1:根据”男”,”女”两种类型的数据,把数据中所有的”男”,”女”转换成数值类型1,0 ,如以下代码所示。

import pandas as pd
data = {'性别': ['男', '女', '男', '女', '女']}
df = pd.DataFrame(data)
df[u'性别_new'] = df[u'性别'].map({'男': 1, '女': 0})
print(df)

结果如下:

  性别  性别_new
0  男       1
1  女       0
2  男       1
3  女       0
4  女       0

数据标准化

数据标准化,我们也可以称之为Z-score标准化。

数据进行分析之前,通常需要先将数据标准化,利用标准化后的数据进行数据分析。数据标准化是一种将整列数据约束在某个范围内的方法,经过标准化处理,原始数据均转换为无量纲化指标测评值,即各指标值都处于同一个数量级别上,可以进行综合测评分析。

如果通过身高体重去分析一个正常身材的人的胖瘦,假设身高的衡量标准为“米”,而体重的衡量标准为“斤”,由于二者的数量级的差异,会导致判断胖瘦的标准发生改变,导致体重一项具有了更大的影响力 ,但是根据经验可以知道,一个正常身材人的胖瘦是由身高和体重共同决定的,对于这样的数据而言,给计算机使用的数据就要进行数据标准化。

数据标准化公式如下:

这里的 代表均值, 代表标准差。

使用numpy和pandas来实现标准化,如以下代码所示。

import numpy as np
import pandas as pd


def ZscoreNormalization(x):
    x = (x - np.mean(x)) / np.std(x)
    return x


Z_views = pd.DataFrame({
    'height': [1.8, 1.7, 1.9, 1.75, 1.68, 1.67],
    'weight': [80, 70, 98, 67, 68, 50]
})
Z_views['zscore_h'] = ZscoreNormalization(views[['height']])
Z_views['zscore_w'] = ZscoreNormalization(views[['weight']])
print(Z_views)

结果如下:

   height  weight  zscore_h  zscore_w
0    1.80      80  0.621770  0.538666
1    1.70      70 -0.621770 -0.148993
2    1.90      98  1.865310  1.776453
3    1.75      67  0.000000 -0.355291
4    1.68      68 -0.870478 -0.286525
5    1.67      50 -0.994832 -1.524311

python中还提供了一个很好用的库sklearn, sklearn是一个基于python的机器学习工具,在这个库中提供了许多简单高效的函数可以作为数据分析的工具,其中StandardScaler()函数就提供了标准化的方法,该函数下的fit_transform能够通过拟合数据的方法得到更好的标准化结果,如以下代码所示。

from sklearn.preprocessing import StandardScaler
import pandas as pd
views = pd.DataFrame({
    'height': [1.8, 1.7, 1.9, 1.75, 1.68, 1.67],
    'weight': [80, 70, 98, 67, 68, 50]
})
ss = StandardScaler()
views['zscore_h'] = ss.fit_transform(views[['height']])
views['zscore_w'] = ss.fit_transform(views[['weight']])
print(views)

结果如下:

   height  weight  zscore_h  zscore_w
0    1.80      80  0.621770  0.538666
1    1.70      70 -0.621770 -0.148993
2    1.90      98  1.865310  1.776453
3    1.75      67  0.000000 -0.355291
4    1.68      68 -0.870478 -0.286525
5    1.67      50 -0.994832 -1.524311

数据归一化

数据归一化,我们也可以称之为Min-Max标准化。

和数据标准化一样,不同评价指标往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行对数据的处理,但是通过上一小节中的结果可以看到,有一些数据经过标准化后出现了负值的情况,而有些时候负数会影响用户的数据质量,本章讲述不会产生负数的标准化方法。

数据归一化会将所有的数据约束到[0,1]的范围内。

数据归一化公式如下:

公式中min(x)表示数据中的最小值,max(x)表示数据中的最大值。

使用numpy和pandas来实现标准化,如以下代码所示。

import numpy as np
import pandas as pd


def MaxMinNormalization(x):
    x = (x - np.min(x)) / (np.max(x) - np.min(x))
    return x


M_views = pd.DataFrame({
    'height': [1.8, 1.7, 1.9, 1.75, 1.68, 1.67],
    'weight': [80, 70, 98, 67, 68, 50]
})
M_views['zscore_h'] = MaxMinNormalization(views[['height']])
M_views['zscore_w'] = MaxMinNormalization(views[['weight']])
print(M_views)

结果如下:

   height  weight  zscore_h  zscore_w
0    1.80      80  0.565217  0.625000
1    1.70      70  0.130435  0.416667
2    1.90      98  1.000000  1.000000
3    1.75      67  0.347826  0.354167
4    1.68      68  0.043478  0.375000
5    1.67      50  0.000000  0.000000

同样在sklearn中也提供了数据归一化的函数MinMaxScaler(),如以下代码所示。

from sklearn.preprocessing import MinMaxScaler
import pandas as pd

views = pd.DataFrame({
    'height': [1.8, 1.7, 1.9, 1.75, 1.68, 1.67],
    'weight': [80, 70, 98, 67, 68, 50]
})

mms = MinMaxScaler()
views['minmax_h'] = mms.fit_transform(views[['height']])
views['minmax_w'] = mms.fit_transform(views[['weight']])
print(views)

结果如下:

   height  weight  minmax_h  minmax_w
0    1.80      80  0.565217  0.625000
1    1.70      70  0.130435  0.416667
2    1.90      98  1.000000  1.000000
3    1.75      67  0.347826  0.354167
4    1.68      68  0.043478  0.375000
5    1.67      50  0.000000  0.000000

03

高级数据预处理方法

在数据预处理的过程中还存在着许多高级的预处理方法, 本章详解两种高级的数据预处理方法,哑变量( Dummy Variables)和独热编码(One-Hot Encoding)。

在掌握两种方法之前,需先了解词语向量化(词向量),词向量就是提供了一种数学化的方法,把自然语言这种符号信息转化为向量形式的数字信息。

哑变量

通常将不能定量处理的变量量化,构造只取“0”或“1”的人工变量,通常称哑变量。

示例1: 现在有性别:{男,女,其他}。性别特征有三个不同的分类值,需要三个bit的值来表示这些类别。

独热码表示为:

男:{01},女:{10},其他:{00}。

多个特征时表示为:

性别:{男,女,其他};性别编码为:男:{01},女:{10},其他:{00}。

年级:{一年级,二年级,三年级};年级编码为:一年级:{10},二年级:{01},三年级:{00}。

对于二年级的男生就可以编码为:{0110}(前面的01表示一年级,后面的10表示男生)。

pandas中提供了get_dummies()函数来实现哑变量,但是需要注意的是该函数生成的数据中不包含全0项,如以下代码所示。

import pandas as pd
df = pd.DataFrame({
   '性别': ['男', '女', '其他'],
   '年级': ['一年级', '二年级', '三年级']
 })
df = pd.get_dummies(df)
print(df)

结果如下:

   性别_其他  性别_女  性别_男  年级_一年级  年级_三年级  年级_二年级
0      0     0     1       1       0       0
1      0     1     0       0       0       1
2      1     0     0       0       1       0

通过结果我们会发现结果和原理不同,为什么给出一个具有全0项的定义方法,下一章独热编码会详细解释其原理。

独热编码

独热编码是表示一项属性的特征向量,向量中只有一个特征是不为0的,其他的特征都为0(简单的来说就是将一个bit的位置填1,其他位置都填0),比如数据挖掘中对于离散型的分类数据,需要对其进行数字化,使用独热码来表示:性别:{男,女,其他}。

可以看到上面的性别特征有三个不同的分类值,也就意味着需要三个bit的值来表示这些类别。

独热码表示:

男:{001},女:{010},其他:{100}

多个特征时表示:

性别:{男,女,其他};性别编码为:男:{001},女:{010},其他:{100}

年级:{一年级,二年级,三年级};年级编码为:一年级:{100},二年级:{001},三年级:{010}

对于二年级的男生编码可以为:{001001}(前面的001表示二年级,后面的001表示男生)

能够发现上一章通过get_dummies()函数得到的结果其实是独热编码的结果,可以说二者在实际原理上是有一定偏差的但是在代码的结果显示上却是一致的。关于python中标准的独热编码如以下代码所示。

import pandas as pd
from sklearn import preprocessing
df = pd.DataFrame({'性别': ['男', '女', '其他'], '年级': ['一年级', '二年级', '三年级']})
ont_hot = preprocessing.OneHotEncoder(categories='auto')
df1 = ont_hot.fit(df)  # 拟合
print("一年级男生的编码为:{}".format(ont_hot.transform([['男', '一年级']]).toarray()))
print("二年级女生的编码为:{}".format(ont_hot.transform([['女', '二年级']]).toarray()))
print("三年级男生的编码为:{}".format(ont_hot.transform([['男', '三年级']]).toarray()))

结果如下:

一年级男生的编码为:[[0. 0. 1. 1. 0. 0.]]
二年级女生的编码为:[[0. 1. 0. 0. 0. 1.]]
三年级男生的编码为:[[0. 0. 1. 0. 1. 0.]]

在独热编码中又一次使用了sklearn库,其中的preprocessing模块中提供了很完美OneHotEncode()函数的使用,优点在于能够对数据进行拟合的操作,拟合好了一个模型之后,输入想要的词条的时候,使用transform()函数就能自动的生成需要的编码形式。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据山谷 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
TI-ONE 训练平台
TI-ONE 训练平台(以下简称TI-ONE)是为 AI 工程师打造的一站式机器学习平台,为用户提供从数据接入、模型训练、模型管理到模型服务的全流程开发支持。TI-ONE 支持多种训练方式和算法框架,满足不同 AI 应用场景的需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档