EDA-数据探索性分析
文章目录
1. EDA介绍
EDA:(Exploratory Data Analysis)是数据收集,学习及操作流程等大量过程中的一部分,又称探索性数据分析。
- EDA的价值主要在于熟悉数据集,了解数据集,对数据集进行验证来确定所获得数据集可以用于接下来的机器学习或者深度学习使用。
- 当了解了数据集之后我们下一步就是要去了解变量间的相互关系以及变量与预测值之间的存在关系。
- 引导数据科学从业者进行数据处理以及特征工程的步骤,使数据集的结构和特征集让接下来的预测问题更加可靠。
2.EDA分析方法
2.1 安装环境
#coding:utf-8
#导入warnings包,利用过滤器来实现忽略警告语句。
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import missingno as msno
2.2 载入数据方法
Train_data = pd.read_csv('train.csv', sep=' ')
Test_data = pd.read_csv('testA.csv', sep=' ')
脱敏处理:指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。这样就可以在开发、测试和其它非生产环境以及外包环境中安全地使用脱敏后的真实数据集。
- name - 汽车编码
- regDate - 汽车注册时间
- model - 车型编码
- brand - 品牌
- bodyType - 车身类型
- fuelType - 燃油类型
- gearbox - 变速箱
- power - 汽车功率
- kilometer - 汽车行驶公里
- notRepairedDamage - 汽车有尚未修复的损坏
- regionCode - 看车地区编码
- seller - 销售方
- offerType - 报价类型
- creatDate - 广告发布时间
- price - 汽车价格
- v_0’, ‘v_1’, ‘v_2’,‘v_3’, ‘v_4’, ‘v_5’, ‘v_6’, ‘v_7’, ‘v_8’, ‘v_9’, ‘v_10’, ‘v_11’,‘v_12’,‘v_13’,‘v_14’(根据汽车的评论、标签等大量信息得到的embedding向量)【人工构造 匿名特征】
## 简略观察数据(head()+shape)
Train_data.head().append(Train_data.tail())
## 查看数据集的形状
Train_data.shape
head()以及tail()分别为pandas查看数据集头尾部数据信息的函数,不佳参数默认查看5条。shape则为返回数据集形状的函数。
参考链接:https://blog.youkuaiyun.com/n1neding/article/details/80395505
2.3 数据集处理方法
2.3.1 数据总览
describe():输出所有列的各参数
count–计数
mean–平均值
std–标准差
min–最小值
max–最大值
25%–第一个四分位数
50%–中位数
75%–第三个四分位数
info():查看数据集中非空数据的类型dtype
columns:查看存在的所有列
## 通过describe()来熟悉数据的相关统计量
Train_data.describe()
## 通过info()来熟悉数据类型
Train_data.info()
## 通过columns来查看列信息
Train_data.columns
2.3.2 判断数据缺失和异常
## 查看每列的存在nan情况
Train_data.isnull().sum()
# nan可视化
missing = Train_data.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar()
可视化查看缺省情况:
# 两种可视化查看缺省值
msno.matrix(Train_data.sample(250))
msno.bar(Train_data.sample(1000))
msno.matrix是使用最多的函数,能快速直观地看到数据集的完整性情况,矩阵显示。
msno.bar可以简单的展示无效数据的条形图。
对缺省数据做预处理:
# 先查看某一元素的缺省分布情况
Train_data['notRepairedDamage'].value_counts()
# 0.0 111361
# - 24324
# 1.0 14315
# Name: notRepairedDamage, dtype: int64
# 可以看出来‘-’也为空缺值,这里我们先替换成nan
# in_place 参数如果为False表示新建个数组进行替换,True则表示就地执行替换操作
Train_data['notRepairedDamage'].replace('-', np.nan, inplace=True)
如果某个类别特征严重倾斜,一般不会对预测有什么帮助,采用的解决方法是先删掉。
Train_data["seller"].value_counts()
del Train_data["seller"]
2.3.3 了解预测值的分布
这里要预测的对象是价格。
Train_data['price']
Train_data['price'].value_counts()
- 总体分布概况(采用无界约翰逊分布、正态分布、和对数正态分布)
displot()集合了matplotlib的hist()与核kde函数估计kdeplot的功能,增加了rugplot分布观测条显示与利用scipy库fit拟合参数分布的新颖用途。
kde核密度估计是在概率论中用来估计未知的密度函数,属于非参数检验方法之一。由于核密度估计方法不利用有关数据分布的先验知识,对数据分布不附加任何假定,是一种从数据样本本身出发研究数据分布特征的方法,因而,在统计学理论和应用领域均受到高度的重视。
import scipy.stats as st
y = Train_data['price']
# distplot中的hist和kde参数默认为True,kde置为False,表示隐藏核函数估计分布的曲线
plt.figure(1); plt.title('Johnson SU')
sns.distplot(y, kde=False, fit=st.johnsonsu)
plt.figure(2); plt.title('Normal')
sns.distplot(y, kde=False, fit=st.norm)
plt.figure(3); plt.title('Log Normal')
sns.distplot(y, kde=False, fit=st.lognorm)
- 查看skewness and kurtosis
sns.distplot(Train_data['price']);
print("Skewness: %f" % Train_data['price'].skew())
print("Kurtosis: %f" % Train_data['price'].kurt())
# 对数据集的Skewness和Kurtosis作图分析
sns.distplot(Train_data.skew(),color='blue',axlabel ='Skewness')
sns.distplot(Train_data.kurt(),color='orange',axlabel ='Kurtness')
Skewness偏度描述数据的对称性,峰度(Kurtosis)描述数据的尖锐程度
注:skew、kurt说明参考:https://www.cnblogs.com/wyy1480/p/10474046.html
2.3.4 数字特征分析
先分离得到数据集中的数字特征。
numeric_features=
['power',
'kilometer',
'v_0',
'v_1',
'v_2',
'v_3',
'v_4',
'v_5',
'v_6',
'v_7',
'v_8',
'v_9',
'v_10',
'v_11',
'v_12',
'v_13',
'v_14',
'price']
- 相关性分析
price_numeric = Train_data[numeric_features]
correlation = price_numeric.corr()
# ascending=True表示从小到大排序,False表示反序
print(correlation['price'].sort_values(ascending = False),'\n')
DataSet.corr() :相关系数矩阵,即给出了任意两个变量之间的相关系数,此处为计算price变量与其他变量之间的关系。
- 查看不同特征的偏度和峰值
# '{:a.bf}'.format()表示取a位长度,小数点后b位的浮点数
for col in numeric_features:
print('{:15}'.format(col),
'Skewness: {:05.2f}'.format(Train_data[col].skew()) ,
' ' ,
'Kurtosis: {:06.2f}'.format(Train_data[col].kurt())
)
# 将其可视化
f , ax = plt.subplots(figsize = (7, 7))
plt.title('Correlation of Numeric Features with Price',y=1,size=16)
# 热度图,square表示绘制成方形
sns.heatmap(correlation,square = True, vmax=0.8)
- 每个数字特征得分布可视化
对比不同特征间的分布程度,跟相关性差不多。
## melt将训练数据集转化成numeric_features特征为变量的表格,将其存储在"variable"中
f = pd.melt(Train_data, value_vars=numeric_features)
# 绘制多个图形,分两列,不共享xy轴
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False)
# distplot集合了matplotlib的hist()与核kde函数估计kdeplot的功能,增加了rugplot分布观测条显示与利用scipy库fit拟合参数分布的新颖用途。即呈现分布。
g = g.map(sns.distplot, "value")
## 数字特征相互之间的关系可视化,生成散点矩阵图
sns.set()
columns = ['price', 'v_12', 'v_8' , 'v_0', 'power', 'v_5', 'v_2', 'v_6', 'v_1', 'v_14']
sns.pairplot(Train_data[columns],size = 2 ,kind ='scatter',diag_kind='kde')
plt.show()
散点图矩阵建立在两个基本图形上,直方图和散点图。对角线上的直方图允许我们看到单个变量的分布,而上下三角形上的散点图显示了两个变量之间的关系。
Pairs Plots学习参考:https://www.jianshu.com/p/5fac2a2b74ff
- 多变量互相回归关系可视化
# Y_train即分离出的价格成员
fig, ((ax1, ax2), (ax3, ax4), (ax5, ax6), (ax7, ax8), (ax9, ax10)) = plt.subplots(nrows=5, ncols=2, figsize=(24, 20))
# ['v_12', 'v_8' , 'v_0', 'power', 'v_5', 'v_2', 'v_6', 'v_1', 'v_14']
v_12_scatter_plot = pd.concat([Y_train,Train_data['v_12']],axis = 1)
sns.regplot(x='v_12',y = 'price', data = v_12_scatter_plot,scatter= True, fit_reg=True, ax=ax1)
v_8_scatter_plot = pd.concat([Y_train,Train_data['v_8']],axis = 1)
sns.regplot(x='v_8',y = 'price',data = v_8_scatter_plot,scatter= True, fit_reg=True, ax=ax2)
v_0_scatter_plot = pd.concat([Y_train,Train_data['v_0']],axis = 1)
sns.regplot(x='v_0',y = 'price',data = v_0_scatter_plot,scatter= True, fit_reg=True, ax=ax3)
power_scatter_plot = pd.concat([Y_train,Train_data['power']],axis = 1)
sns.regplot(x='power',y = 'price',data = power_scatter_plot,scatter= True, fit_reg=True, ax=ax4)
v_5_scatter_plot = pd.concat([Y_train,Train_data['v_5']],axis = 1)
sns.regplot(x='v_5',y = 'price',data = v_5_scatter_plot,scatter= True, fit_reg=True, ax=ax5)
v_2_scatter_plot = pd.concat([Y_train,Train_data['v_2']],axis = 1)
sns.regplot(x='v_2',y = 'price',data = v_2_scatter_plot,scatter= True, fit_reg=True, ax=ax6)
v_6_scatter_plot = pd.concat([Y_train,Train_data['v_6']],axis = 1)
sns.regplot(x='v_6',y = 'price',data = v_6_scatter_plot,scatter= True, fit_reg=True, ax=ax7)
v_1_scatter_plot = pd.concat([Y_train,Train_data['v_1']],axis = 1)
sns.regplot(x='v_1',y = 'price',data = v_1_scatter_plot,scatter= True, fit_reg=True, ax=ax8)
v_14_scatter_plot = pd.concat([Y_train,Train_data['v_14']],axis = 1)
sns.regplot(x='v_14',y = 'price',data = v_14_scatter_plot,scatter= True, fit_reg=True, ax=ax9)
v_13_scatter_plot = pd.concat([Y_train,Train_data['v_13']],axis = 1)
sns.regplot(x='v_13',y = 'price',data = v_13_scatter_plot,scatter= True, fit_reg=True, ax=ax10)
2.3.5 类别特征分析
分离出类别特征。
categorical_features =
['name',
'model',
'brand',
'bodyType',
'fuelType',
'gearbox',
'notRepairedDamage',
'regionCode']
- 类别特征箱形图可视化
# 先剔除 name和 regionCode两个稀疏的类别
categorical_features = ['model',
'brand',
'bodyType',
'fuelType',
'gearbox',
'notRepairedDamage']
# 将类别特征中缺省值填充为MISSING
for c in categorical_features:
Train_data[c] = Train_data[c].astype('category')
if Train_data[c].isnull().any():
Train_data[c] = Train_data[c].cat.add_categories(['MISSING'])
Train_data[c] = Train_data[c].fillna('MISSING')
# 定义箱型图表函数
def boxplot(x, y, **kwargs):
sns.boxplot(x=x, y=y)
# x轴标签逆时针旋转90度
x=plt.xticks(rotation=90)
# id_vars值即保留price不被转换
f = pd.melt(Train_data, id_vars=['price'], value_vars=categorical_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5)
g = g.map(boxplot, "value", "price")
- 类别特征的小提琴图可视化
catg_list = categorical_features
target = 'price'
for catg in catg_list :
sns.violinplot(x=catg, y=target, data=Train_data)
plt.show()
- 类别特征的柱形图可视化
def bar_plot(x, y, **kwargs):
sns.barplot(x=x, y=y)
x=plt.xticks(rotation=90)
# id_vars值即保留price不被转换
f = pd.melt(Train_data, id_vars=['price'], value_vars=categorical_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5)
g = g.map(bar_plot, "value", "price")
- 类别特征的每个类别频数可视化(count_plot)
def count_plot(x, **kwargs):
sns.countplot(x=x)
x=plt.xticks(rotation=90)
f = pd.melt(Train_data, value_vars=categorical_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5)
g = g.map(count_plot, "value")
2.3.6 用pandas_profiling生成数据报告
import pandas_profiling
pfr = pandas_profiling.ProfileReport(Train_data)
pfr.to_file("./example.html")
3. EDA小结
数据探索在机器学习中我们一般称为EDA(Exploratory Data Analysis):
是指对已有的数据(特别是调查或观察得来的原始数据)在尽量少的先验假定下进行探索,通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律的一种数据分析方法。
数据探索有利于我们发现数据的一些特性,数据之间的关联性,对于后续的特征构建是很有帮助的。
-
对于数据的初步分析(直接查看数据,或.sum(), .mean(),.descirbe()等统计函数)可以从:样本数量,训练集数量,是否有时间特征,是否是时许问题,特征所表示的含义(非匿名特征),特征类型(字符类似,int,float,time),特征的缺失情况(注意缺失的在数据中的表现形式,有些是空的有些是”NAN”符号等),特征的均值方差情况。
-
分析记录某些特征值缺失占比30%以上样本的缺失处理,有助于后续的模型验证和调节,分析特征应该是填充(填充方式是什么,均值填充,0填充,众数填充等),还是舍去,还是先做样本分类用不同的特征模型去预测。
-
对于异常值做专门的分析,分析特征异常的label是否为异常值(或者偏离均值较远或者事特殊符号),异常值是否应该剔除,还是用正常值填充,是记录异常,还是机器本身异常等。
-
对于Label做专门的分析,分析标签的分布情况等。
-
进步分析可以通过对特征作图,特征和label联合做图(统计图,离散图),直观了解特征的分布情况,通过这一步也可以发现数据之中的一些异常值等,通过箱型图分析一些特征值的偏离情况,对于特征和特征联合作图,对于特征和label联合作图,分析其中的一些关联性。