数据预处理是指因为算法或者分析需要,对经过数据质量检查后的数据进行转换、衍生、规约等操作的过程。整个数据预处理工作主要包括五个方面内容:简单函数变换、标准化、衍生虚拟变量、离散化、降维。本文将作展开介绍,并提供基于Python的代码实现。
1. 简单函数变换
简单函数变换是指对原始数据直接使用某些数学函数进行转换,主要用于将不具有正态分布的数据变换成具有正态分布,同时也可以用于对数据进行压缩,比如\(10^8和10^9\)更关注的是相对差距而不是绝对差距,可以通过取对数变换实现。
常用的函数包括:\(log(x)、x^k、e^x、\frac {1}{x}、\sqrt{x}、sinx\)等。
简单函数变换会改变的原始数据的分布特征,因此使用前必须深入了解数据特征变化是否会影响到后续的分析。
## 导入库
import pandas as pd
import numpy as np
## 读取数据
dataset = pd.read_excel("/labcenter/python/dataset2.xlsx")
## 简单函数变换
dataset['new_col2'] = np.log10(dataset['col2'])
#取10为底的对数
dataset['new_col2'] = np.exp(dataset['col2'],2)
#取平方
dataset['new_col2'] = np.exp(dataset['col2'])
#取e为的底的指数
dataset['new_col2'] = 1 / dataset['col2']
#取倒数
dataset['new_col2'] = np.sqrt(dataset['col2'])
#开方
dataset['new_col2'] = np.sin(dataset['col2'])
#取正弦
2. 标准化
标准化,是为了处理不同规模和量纲的数据,使其缩放到相同的数据区间和范围,以减少规模、量纲、分布差异等对分析建模的影响。常用的标准化方法有以下三种:
2.1 离差标准化
离差标准化,又称最大值最小值标准化(Max-Min),即基于原始数据的最大值、最小值对数据进行线性变换,变换后,数据完全落入[0,1]区间内。
公式:
\[x'= \frac {(x-min)}{(max-min)}\]
其中,原始数据x,其最大值、最小值分别为max、min,转换后数据为x'。
优点:能够将数据归一化,同时能较好的保持原始数据的分布结构;
缺点:容易受极端值的影响,极端值会使大部分数据接近于0并且差距很小,同时在出现最值范围以外的数据时变换结果会产生错误;
适用场景:适合数据比较集中的情况。
2.2 标准差标准化
标准差标准化,即Z-Score标准化,即基于原始数据的均值和标准差对数据进行标准化,标准化后,数据呈正态分布。
公式:
\[x'= \frac {(x-μ)}{σ}\]
其中,原始数据x,其均值、标准差分别为μ、σ,转换后数据为x'。
缺点:是一种中心化方法,会改变原始数据的分布结构。
适用场景:适合数据的最值未知,且可能出现离群点的情况。
2.3 绝对值最大标准化
绝对值最大标准化,即MaxAbs标准化,即基于原始数据绝对值的最大值对数据进行标准化,变换后,数据完全落入[-1,1]区间内。
公式:
\[x'= \frac {x}{maxAbs}\]
其中,原始数据x,其绝对值的最大值为maxAbs,转换后数据为x'。
优点:不会破坏原始数据的分布结构;
适用场景:可用于稀疏矩阵、稀疏数据。
## 标准化处理
## 方法1:使用numpy和pandas
### 离差标准化
dataset['new_col2'] = (dataset['col2'] - dataset['col2'].min()) / (dataset['col2'].max() - dataset['col2'].min())
### 标准差标准化
dataset['new_col2'] = (dataset['col2'] - dataset['col2'].mean()) / dataset['col2'].std()
### 绝对值最大标准化
dataset['new_col2'] = dataset['col2'] / np.abs(dataset['col2']).max()
## 方法2:使用sklearn
from sklearn import preprocessing
### 离差标准化
minmax_scaler = preprocessing.MinMaxScaler()
dataset['new_col2'] = minmax_scaler.fit_transform(dataset['col2'])
### 标准差标准化
zsocre_scaler = preprocessing.StandardScaler()
dataset['new_col2'] = zsocre_scaler.fit_transform(dataset['col2'])
### 绝对值最大标准化
maxabs_scaler = preprocessing.MaxAbsScaler()
dataset['new_col2'] = maxabs_scaler.fit_transform(dataset['col2'])
3. 衍生虚拟变量
在数据建模过程中,很多算法都不能处理非数值型数据,必须首先将这些数据转化为数值型。但是,即使转化为数值型数据,也不能直接应用到算法计算中,为什么?这需要从离散型数据的分类说起。
离散型数据也就是分类数据,主要分为两类,一类是无序分类,一类是有序分类。
无序分类,是指各个类别之间没有明显的高、低、大、小等包含等级、顺序、优劣、好坏等逻辑的划分,只是用来区分两个或多个具有相同或相当价值的属性。例如性别的男和女,颜色的红、黄、蓝等等。
有序分类,是指各个类别之间有一定的顺序关系。例如用户价值的高、中、低,学历的博士、硕士、学士等。
对于无序分类来说,无论用什么数值来表示都无法表达出价值相等但有区分的属性,比如性别的男和女,如果分别用1和2表示,那么1和2本身就已经带有距离为1的差异,但实际上二者之间是没有这种差异的,同样,不论用任何数据都无法到达这种区分的目的。
而对于有序分类来说,无论用什么有序的数字序列都无法准确表达出有序类别之间的差异性,比如学历的博士、硕士、学士,如果用3-2-1来表示这种顺序关系,那这种差异为什么不能用30-20-10来表示呢?
所以,非数值型的离散型数据要想参与到算法计算中,不能简单的认为转化成用数值就表示就可以,而是必须使用其他的方法,这种方法就是衍生虚拟变量,也叫做创建虚拟变量(dummy variable)、创建哑变量、创建名义变量、one-hot编码(one-hot encoding)、N取一编码(one-out-of encoding)。它是指,将一个离散型变量衍生出多个真值变量(用0和1,或者True和False表示的变量),比如性别这一变量取值有男、女两个,那么将衍生出性别是否男、性别是否女两个变量;然后使用这些衍生出来的真值变量替换原始变量参与后续的计算。
## 衍生虚拟变量
## 方法1:自定义函数
def dummyCreate(ser):
valueSet = ser.unique()
resDf = pd.DataFrame()
colName = ser.name
for value in valueSet:
colNameNew = colName + '_' + value
colDataTmp = ser.values
colData = (colDataTmp == value)
resDf[colNameNew] = colData
return resDf
dummyCreate(dataset['col3'])
## 方法2:使用sklearn
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
labelEnc = LabelEncoder() ##标准标签化
ohEnc = OneHotEncoder()
##one-hot编码
dataset['new_col3'] = labelEnc.fit_transform(dataset['col3']) ##将类别值用0.1.2……编码
ohEncRes = ohEnc.fit_transform(dataset['new_col3'].reshape(-1,1)).toarray()
##one-hot编码
newDf = pd.concat((dataset, pd.DataFrame(ohEncRes)), axis=1) ##合并结果
dataset = newDf.rename(columns={0:'col3_aaa',1:'col3_bbb',2:'col3_ccc'}) ##重命名列名