在机器学习过程中,我们往往需要对数据进行预处理。根据数据的取值情况,我们可以把数据总体分为两大类:类别型数据和数值型数据。
1. 为什么需要编码
机器学习相关算法对各数据进行衡量时,依赖的大多是其数值关系,如决策树ID3算法依赖于香农熵的计算,线性回归模型依赖于欧式距离的计算。
数值型变量自然是可以直接被算法处理,而算法往往无法直接对分类型变量进行处理,因此在把数据应用于算法训练前,需要对其进行调整,把分类型变量转换成为数值。
2. 主要编码方式
2.1 Replace 直接替换
有些时候,在我们要进行特征处理的变量中,并不是所有的取值都需要进行特征处理,只需要对其中部分不符合要求的取值进行替换。
举例如下:
假设 test_df 包含的是8名同学在某次测验中的数学成绩,成绩记录的标准为:
-
成绩低于60分,记为F
-
成绩在[60, 70)之间,记为C
-
成绩在[70, 80)之间,记为B
-
成绩在[80, 100]之间,记为A
在记录的过程中,由于疏忽,一名同学的成绩被错记为其真实的数值成绩。
所以,在本数据集中需要对其进行特征编码,将该数值根据成绩记录的标准进行替换,以使得最终 math 变量的取值标准统一。
在本案例中,则需要将 93 替换为 A。可以考虑直接使用 Replace() 方法进行处理。
代码如下:
test_dict = {'id': [1, 2, 3, 4, 5, 6, 7, 8], # 构建测试数据``
'math':['F', 'B', 'B', 'F', 93, 'A', 'C', 'C']}
test_df = pd.DataFrame(test_dict)
# 将math一列中的93替换成A
test_df.replace({'math': {93: 'A'}}, inplace=True)
test_df
显示结果如下:
2.2 map() 替换
除了使用 replace() 方法,也可以应用内置的 map() 方法进行直接替换处理。
map() 可以对 Dataframe 中某列内的元素进行操作,在此情景下的作用是:根据映射关系,为指定列匹配结果并进行替换。其处理原理与使用 replace() 进行直接替换的方式一致,需要自行指定各类别取值应该如何转换为数值。
但其特别之处在于,map() 方法作用于整列变量的元素,因此需要对该列变量中所有可能出现的取值指定映射关系,否则没有指定映射关系的取值将会被转换成NaN。因此,不适用于取值类别特别多的时候。
例一:没有指定全部映射关系,出现 NaN
借用讲述 replace() 部分的案例,我们要做的工作是将93转换成为A。
如果使用 map() 方法,并只对93进行转换,而没有对所有取值指定映射关系。上例案例可以修改为:
test_df['math'] = test_df['math'].map({93: 'A'})
test_df
处理后的数据对比:
可以看出,这里的 map() 只对93进行了转换,而 math 变量中其余取值都变成了 NaN。
例二:将 art 变量的取值全部进行映射处理
假设art变量共5个取值:[a1, a2, a3, b1, b2]。现在需要将[a1, a2, a3]转换为a,[b1, b2]转换为b。
代码如下:
import pandas as pd
test_df2 = pd.DataFrame({'id': [1, 2, 3, 4, 5],
'art': ['a1', 'a2', 'b1', 'a3', 'b2']})
# 对art变量的取值一一构建映射关系,并进行替换
test_df2['art'] = test_df2['art'].map({'a1': 'a', 'a2': 'a', 'a3': 'a',
'b1': 'b', 'b2': 'b'})
test_df2
显示结果如下:
2.3
直接替换方法适用于原始数据集中只存在少量数据需要人工进行调整的情况。如果需要调整的数据量非常大且数据格式不统一,直接替换的方法也可以实现我们的目的,但是这种方法需要的工作量会非常大。因此, 我们需要能够快速对整列变量的所有取值进行编码的方法。