在数据挖掘过程中,数据预处理是不可或缺的部分
数据源:Oracle,SQL Server,Flat Data,Teradata 抽取中需要注意的点:
数据转换一般包括清洗和转换两部分:
在实际业务中,大多数情况下从数据源抽取的数据都经过转换,整合处理后输入到数据目的地中 在实际业务中,也存在高质量的数据,无需经过转换操作,源数据直接到达数据目的地,这种数据叫做Pass Through Data
加载是ETL中最后一步,是将已转换后的数据加载到指定的数据仓库中,为后续数据的分析,挖掘提供数据准备
DataStage | Kettle | Informatica | |
---|---|---|---|
费用 | 价格昂贵 | 开源 | 费用比DataStage稍低 |
易用性 | 有GUI界面 | 有GUI界面 | 有GUI界面 |
数据质量 | 有专门的数据质量管理产品ProfileStage和QualityStage | 在GUI里有数据质量管理,通过SQL语句,JAVA脚本,正则表达式进行数据清洗 | 有专门的数据质量产品FirstLogic |
源数据支持 | 有专门的源数据管理工具MetaStage | 支持广泛的数据库,数据文件等,同时支持扩展 | 有专门的源数据管理工具Superglue |
除了上述工具以外,还可构建ELT开源数据平台,使用较为广泛的是Kafka Connect,DataX等,也可以直接采用Flink等流式计算框架和Hive代替传统的ETL和ELT工具
数据清洗是指通过删除,转换,组合等方法,处理数据集中的异常样本,为数据建模提供优质数据的过程
在实际业务中,不可避免的会出现数据缺失的现象,总结下来大致有如下几种情形:
数据集中不含缺失值的变量称为完全变量,数据集中含有缺失值的变量称为不完全变量。数据缺失类型可以分为完全随机缺失,随机缺失和非随机缺失。
数据缺失类型可以分为完全随机缺失,随机缺失和非随机缺失。
数据缺失原因多种多样,针对不同的缺失原因,数据缺失值的处理方式也各不相同。值得注意的是,有时属性缺失并不意味着数据缺失,比如,银行收集客户信息时,学生在“工资”这一栏为空值。缺失本身是包含有价值的信息的。因此要结合具体业务场景、数据场景选择合适的数据缺失值处理方式。 缺失值处理方法众多,总结下来为三种:
缺失值操作的Python代码(删除缺失值):
import pandas as pd
df = pd.read_csv('wine_old.csv')
df.head()#显示前五行
#缺失值检测
df.isnull().any() #按列进行缺失值检测,一列中有任意位置有缺失值,返回True,否则返回False
df.isnull().sum() #返回每一列中缺失值的数量
df.shape #获取数据的形状
#缺失值占比
df.isnull().sum()/178 * 100
#画柱状图
import missingno as miss
miss.bar(df)
# 缺失值处理----删除
df.dropna(axis=1,how='any',thresh=178 * 0.9,inplace=True)#按列删除,一列中只要有缺失值就删除,删除阈值是90%
#也就是说,完整的值要在这一列中超过90%,这一列才能被保留,inplace表示是否在源数据上操作,如果是True
#表示在源数据上操作,相当于永久修改了,如果是False,则表示在源数据的副本上操作,原数据没变,推荐使用
#False,万一改错了呢
#单独删除列
del df_na['type']
df_na
基于统计学原理,根据初始数据集中非缺失对象取值的分布情况来对一个缺失值进行填充。 填充方式包含人工填充、特殊值填充、平均值填充、热卡填充、KNN、预测模型、组合完整化方法等。 我们主要学习
填充-Mean/Mode/Median估计
缺失值处理----填充 缺失值的形式:
替换缺失值: 这部分代码适合于数据中数值型的列和字符串型的列都存在缺失值的情况
# df_na.info()
#查看一列中值的分布
# df_na['malic'].value_counts()
#查看malic这一列的众数
df_na['malic'].mode()
#用malic这一列的一个众数,替换这一列中的空格,因为这一列有一个空值是用空格来表示的,因此这一列为object类型,不能直接算平均数或者中位数,只能先用众数来替换这个空格
df_na['malic'] = df_na['malic'].replace(to_replace=' ',value=df_na['malic'].mode()[0])
#替换完了之后,把整个这一列类型转换成float64,这样这一列就可以计算平均数了
import numpy as np
df_na['malic'] = df_na['malic'].astype(np.float64)
#类型转换完成以后,就可以利用平均数替换其他标准的空值了
df_na['malic'] = df_na['malic'].replace(to_replace=np.nan,value=df_na['malic'].mean())
缺失值填充方法二:只能选择一种填充(均值,众数,中位数)
from sklearn.impute import SimpleImputer
#定义规则(参数)
model_fill = SimpleImputer(missing_values=np.nan,strategy='most_frequent')
#将规则应用到数据上
df_fill = model_fill.fit_transform(df_na)
#转型(将数据转换成DataFrame类型)
df_df = pd.DataFrame(df_fill,columns=df_na.columns)
KNN
回归
变量映射
异常值是偏离整体样本的观察值,也叫离群点(Qutlier) 异常值会影响数据模型的精确度,因此异常值处理是数据预处理中重要的一步,在实际应用中,研究者可将其用于一些异常检测场景,比如入侵检测,欺诈检测,安全监测等
当异常值出现时,需了解异常出现的原因。针对不同原因,采取不同异常值处理方法,以便达到较好的数据挖掘效果。 异常值出现的原因大致有以下几种:
当出现异常值时,会产生以下几种影响:
异常值检测方法较多,本节主要介绍其中四种:散点图、基于分类模型的异常检测、3σ原则及箱型图分析。
sfw = df_na['ash'].describe()
#获取上四分位数
Q1 = sfw["75%"]
# 获取下四分位数
Q2 = sfw["25%"]
#获取IOR
IOR = Q1 - Q2
for x in df_na['ash']:
if x > Q1 + 1.5 * IOR or x < Q2 - 1.5 * IOR:
print(x)
异常值检测---3σ原则
import numpy as np
#计算平均数
mean = df_na['ash'].mean()
#计算标准差
std = np.std(df_na['ash'])
for x in df_na['ash']:
#判断该列中的每个值与平均值的差的绝对值是否大于3倍标准差
if np.abs(x - mean) > 3 * std:
print(x)
#接上一段代码,x为发现的异常值,用平均数替换x,就在原数据上改
df_na['ash'].replace(x,value=df_na['ash'].mean(),inplace=True)
#绘制箱型图
import matplotlib.pyplot as plt
plt.boxplot(df_na['ash'])
特征工程是通过对原始数据处理和加工,将原始数据的属性转换为数据特征的过程。特征工程涵盖很多方面,其中较重要的部分是特征处理和特征选择。
案例引入 假设住房价格受住房面积和卧室数量的影响。基于此假设,研究人员可用住房面积和卧室数量这两个参数预测房价。已知住房面积范围在[100,400](平方米),卧室数量范围在[2,4](间)。由此可见,住房面积这一属性值域范围较大,在建立相关模型预测房价时可能会出现仅住房面积这一属性就可预测出房价的现象,弱化了其他属性在数据模型中的作用,造成一定的预测误差。 必要性
标准化是将训练集中的某一列 (特征) 缩放成均值为0,方差为1的状态。对特征向量进行缩放是无意义的,比如对班级、年龄、性别一组特征向量 (行) 进行标准化操作是无价值的。标准化要求原始数据近似满足高斯分布,数据越接近高斯分布,标准化效果越佳
x'=\frac{x-\mu}{\sigma}
特点
from sklearn.preprocessing import StandardScaler
#定义规则
model_ss = StandardScaler()
#应用到数据上
df_ss = model_ss.fit_transform(df_na[[col for col in df_na.columns if col != "type"]])
#类型转换
df_ss = pd.DataFrame(df_ss,columns=[col for col in df_na.columns if col != "type"])
df_ss
运行结果:
定义:将训练集中某一列特征数值缩放到0-1或者-1-1之间
x'=\frac{x-min(x)}{max(x)-min(x)}
特点:
from sklearn.preprocessing import MinMaxScaler
#设置归一化范围是[-1,1],默认是[0,1]
model_mm = MinMaxScaler(feature_range=(-1,1))
df_mm = model_mm.fit_transform(df_na[[col for col in df_na.columns if col != 'type']])
df_mm = pd.DataFrame(data=df_mm,columns=[col for col in df_na.columns if col != 'type'])
df_mm
运行结果:
提升模型精度 在多属性指标模型中,不同的属性可能会有较大的取值差距,比如属性一取值范围[10000,3000000],属性二取值范围[10,30]。如果直接用原始数据进行分析,可能会造成属性一对最终模型影响较大,相对弱化属性二指标的作用。因此,为保证结果可靠性,需对原始数据进行特征缩放操作。在涉及到距离计算时效果较明显。 提升收敛速度 对于线性模型来说,特征缩放后,最优解的寻优过程会变得平缓,更容易收敛到最优解
import pandas as pd
df = pd.read_csv('wine_old.csv')
#利用cut方法,将数据等宽的离散成3份,分别赋予标签
df['proline'] = pd.cut(df['proline'],3,labels=['low','middle','high'])
df.head()
运行结果:
等频离散化的代码部分
import pandas as pd
df = pd.read_csv('wine_old.csv')
df['alcohol'] = pd.qcut(df['alcohol'],3,labels=['low','middle','high'])
df.head()
数据挖掘中,一些算法可以直接计算分类变量,比如决策树模型。但许多机器学习算法不能直接处理分类变量,它们的输入和输出都是数值型数据。因此,把分类变量转换成数值型数据是必要的,可以用独热编码 (One-Hot Encoding) 和哑编码 (Dummy Encoding)实现。 比较常用的是对逻辑回归中的连续变量做离散化处理,然后对离散特征进行独热编码 (One-Hot Encoding) 或哑编码 (Dummy Encoding),这样会使模型具有较强的非线性能力。
使用M位状态寄存器对M个状态进行编码,每个状态都有独立的寄存器位,这些特征互斥,所以在任意时候只有一位有效。也就是说,这M种状态中只有一个状态位值为1,其他状态位都是0。换句话说,M个变量用M维表示,每个维度的数值或为1,或为0 独热编码的代码部分:
import pandas as pd
df = pd.read_csv('wine_old.csv')
df['alcohol'] = pd.qcut(df['alcohol'],3,labels=['low','middle','high'])
df_oh = pd.get_dummies(df)
df_oh
运行结果:
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
df = pd.read_csv('wine_old.csv')
df['alcohol'] = pd.qcut(df['alcohol'],3,labels=['low','middle','high'])
model_one_hot = OneHotEncoder()
df_one_hot = model_one_hot.fit_transform(df)
df_one_hot
运行结果:
哑编码和独热编码很相似,唯一的区别在于哑编码使用M-1位状态寄存器对M个状态进行编码
有序分类变量数值之间存在一定的顺序关系,可直接使用划分后的数值进行数据建模。 如分类变量{低年级,中年级,高年级},可以直接离散化为{0,1,2}。 在Python中可以用pandas库中的map函数实现有序分类变量的离散化。 Label-Encoding部分代码:
import pandas as pd
df = pd.read_csv('wine_old.csv')
df['alcohol'] = pd.qcut(df['alcohol'],3,labels=['low','middle','high'])
df['alcohol'] = df['alcohol'].map({'low':0,'middle':1,'high':2})
df.head()
运行结果:
在实际业务中,时间数据是经常用到的数据信息。在数据预处理中可能存在 日期格式 - 字符串格式 - 数值格式之间的相互转换。 Python中常用的datetime模块解决大多数日期和时间的处理问题。若需解决更复杂的时间问题,比如:日期计算,可用dateutil模块。
类别数据不均衡是分类任务中存在的经典问题,一般在数据清洗环节进行处理。不均衡简单来说,在数据集中,一类样本的数据量明显远大于其它样本类别数据量。比如,在1000条用户数据中,男性数据有950条,女性数据只有50条
重新采样数据 重采样是不均衡数据处理的常用方法之一,其分为欠采样和过采样两种方法。以下将数据量大的数据类别定义为丰富类,数据量少的数据类别定义为稀有类。
适用于大数据集,从丰富类中随机选择少量样本,再合并原有稀有类作为新的训练数据集。
适用于小数据集,从稀有类中随机选择样本,再合并原有丰富类作为新的训练数据集。 方法 Python中SMOTE算法。
将数据集分为K份,(K-1)份为训练集,其余为测试集。计算K次后取其平均值。
适用于数据集样本分布极其不平衡的现象。当遇到此类情况时,可转换为异常检测问题或一分类问题。典型运用:one class SVM (后续章节详细讲解SVM)。 组合不同的重采样数据集 核心原理:建立N个模型。 假设存在100个稀有数据,则从丰富类中随机抽样出1000 (100*10) 个数据。将这1000个数据分成N份,分别和100个稀有数据合并建立模型。
本文章使用limfx的vscode插件快速发布