EDA-数据探索性分析(二手车交易价格预测))

本文详细介绍了如何进行EDA(Exploratory Data Analysis)以预测二手车交易价格。内容涉及数据载入、初步观察、缺失值和异常值检测、预测值分布分析以及特征分析。使用了Python的数据科学库如pandas、numpy和可视化库matplotlib、seaborn。通过describe、info、缺失值可视化等方法检查数据,并探讨了如何处理缺失值和异常值。同时,还讨论了预测值的分布及特征的相关性和可视化。最后,利用pandas_profiling生成了数据报告,为后续的建模工作提供指导。
摘要由CSDN通过智能技术生成

目标

  • EDA的价值主要在于熟悉和了解数据集,验证数据集是否可以用于接下来的机器学习和深度学习的使用
  • 了解数据集之后去了解变量间的相互关系以及变量于预测值之间的关系
  • 引导数据科学从业者进行数据处理以及特征工程的步骤,使数据集的结构和特征集让接下来的预测问题更加可靠

主要内容

  1. 函数载入
  1. 数据载入
  • 载入训练集和测试集
  • 数据简略观测
    • head()查看前5条数据
    • tail()查看后5条数据
    • shape查看数据维度
  1. 数据总览
  • 相关统计量:describe()可以计算每一列的最大值,最小值,均值,方差等
  • 数据类型:info()查看每一列数据的类型
  1. 数据检测
  • 缺失值检测:查看每列存在的nan
  • 异常值检测
  1. 预测分布
  1. 特征分析
  • 数字特征
    • 查看分析(相关性分析,查看特征的偏度和峰度)
    • 可视化(数字特征之间的关系可视化,多变量互相回归关系。数字特征分布)
  • 类别特征
    • 查看分析(unique分布)
    • 可视化(箱型图,小提琴图,柱形图,各类别频数)
  1. 生成报告:用pandas_profiling生成数据报告

代码示例

载入数据科学库和可视化库

没有的包可以通过pip install安装

#导入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

载入数据

  • CSV格式数据
#载入数据
path='./datasets/'
Train_data=pd.read_csv(path+'used_car_train_20200313.csv',sep=' ')
Test_data=pd.read_csv(path+'used_car_testA_20200313.csv',sep=' ')
  • Excel文件的读取和保存
#读取
dataframe=pd.read_excel('文件名.xlsx')
#保存
dataframe=pd.DataFrame(数据源)
dataframe.to_excel('文件名.xlsx',sheet_name='表名')
  • sql文件读取:read_sql
    读取sql文件之前需要安装好mysql以及python连接mysql的模块PyMySQL,直接命令pip install pymysql。

在数据库中新建一个数据库test,然后新建一个表students,插入数据。

在读取mysql数据之前要将mysql的服务启动:net start mysql。

import pymysql
import pandas as pd
#连接数据库为test
conn=pymysql.connect(host="127.0.0.1",user="root",passwd="123456",db="test")
#查询的表为students
sql="select * from students"
data=pd.read_sql(sql,conn)
print(data)
  • 读取html文件:read_html
import pandas as pd
htl=pd.read_html('E:\test.html')
print(htl)
  • 读取文本数据(txt文件、dat文件、out文件):read_table
def text_save(filename, data):#filename为写入CSV文件的路径,data为要写入数据列表.
    file = open(filename,'a')
    for i in range(len(data)):
        s = str(data[i]).replace('[','').replace(']','')#去除[],这两行按数据不同,可以选择
        s = s.replace("'",'').replace(',','') +'\n'   #去除单引号,逗号,每行末尾追加换行符
        file.write(s)
    file.close()
    print("保存文件成功")
  • json文件读取
#调用read函数全部读取json文件中的数据会报错,因为不能同时读取相同的json对象。需要用readlines()函数,一行一行的读取。
import json
with open('data.json','r') as f:
   data=f.read()
   data=json.loads(data)
   print(data)

#调用readlines()函数读取,并加载进一个列表当中
data_list=[]
with open(r'data.json','r') as f:
   for line in f.readlines():
       dic = json.loads(line)
       data_list.append(dic)

简略观察数据

#2) 简略观察数据(head()+shape)可以查看训练集的前5行数据
Train_data.head().append(Train_data.tail())
#使用shape函数查看训练集的维度
Train_data.shape

测试集可以使用同样的方法,只需将Train_data改成Test_data,要养成看数据集的head()和shape的习惯

总览数据概况

  • describe 有每个特征的统计量,个数count、平均值mean、方差std、最小值min、中位数25% 50% 75% 、以及最大值 看这个信息主要是瞬间掌握数据的大概的范围以及每个值的异常值的判断,比如有的时候会发现999 9999 -1 等值这些其实都是nan的另外一种表达方式,观察每个特征的几种统计变量结果中有没有哪个结果是和其他结果有明显的差异的,如果有的话说明这个特征可能有异常,需要特别关注一下这个特征
  • info 通过info来了解数据每列的type,有助于了解是否存在除了nan以外的特殊符号异常
#1) 通过describe()来熟悉数据的相关统计量
Train_data.describe()
Test_data.describe()
#2) 通过info()来熟悉数据类型
Train_data.info()
Test_data.info()

判断数据缺失和异常

数据缺失

#1) 查看每列的存在nan情况,Isnull()返回bool值元素的列表,用.sum()统计每个特征nan值总量
Train_data.isnull().sum()

nan可视化可以清楚地看出哪些特征存在nan值,以及他们的数量大小
Note:nan值不是空值,是非数

#nan可视化
missing = Train_data.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar()

通过以上两句可以很直观的了解哪些列存在 “nan”, 并可以把nan的个数打印,主要的目的在于 nan存在的个数是否真的很大,如果很小一般选择填充,如果使用lgb等树模型可以直接空缺,让树自己去优化,但如果nan存在的过多、可以考虑删掉

#可视化看下缺省值
msno.matrix(Train_data.sample(250))

从数据集里面抽取250个样本观察特征的缺省值情况,还可以在右侧看到样本的最多特征值个数和最小特征值个数
Note:许多人认为缺省值就是null值,事实上缺省值是default-value,而null值是空值,是缺省值的一种,常用的缺省值还有0和False,一般如果还有其他的缺省值存在,会先转换成nan,在处理
也可以这样查看缺省值

msno.bar(Train_data.sample(1000))

对测试集进行相同的操作可以看出测试集的缺省值和训练集的情况差不多

  • 缺失值处理方式
    • 连续性
      直接删除
    1. 直接删除含有缺失值的行或列
    2. 计算缺失值的个数,如果超过一定数,在删除
      插补(适用于缺失值少)
    3. 固定插补
    4. 均值插补
    5. 中值插补
    6. 最近数据插补
    7. 回归插补
    8. 拉格朗日插补
    9. 牛顿差值
    10. 分段插值
    11. K-means
    12. KNN填补空值
      拟合(适用于缺失值多)
    13. 回归预测
    14. 极大似然估计
    15. 多重插补
    16. 随机森林

数据异常

首先用info()查看个特征的类型

Train_data.info()

发现除了notRepairedDamage 为object类型,其他的都为数字,可以将他的不同值显示一下

Train_data['notRepairedDamage'].value_counts()

可以看出来‘-’也为空缺值,因为很多模型对nan有直接处理,所以这里将它替换成nan,

Train_data['notRepairedDamage'].replace('-', np.nan, inplace=True)
Train_data['notRepairedDamage'].value_counts()

使用value_counts()查看特征的取值情况,可以将严重倾斜的特征删去,这些特征对预测一般不会有什么帮助,也可以继续挖掘,但是意义不大,比如特征seller和offerType,所以使用del语句将训练家和测试集里面的对应特征删去

for fea in Train_data.columns:
    if len(Train_data[fea].value_counts())<=2:
        print(fea)
        print(Train_data[fea].value_counts())
del Train_data["seller"]
del Train_data["offerType"]
del Test_data["seller"]
del Test_data["offerType"]
  • 异常值处理方式
  1. 视为缺失值:修补(平均数、中位数等)
  2. 直接删除:是否要删除异常值可根据实际情况考虑。因为一些模型对异常值不很敏感,即使有异常值也不影响模型效果,但是一些模型比如逻辑回归LR对异常值很敏感,如果不进行处理,可能会出现过拟合等非常差的效果。
  3. 不处理:直接在具有异常值的数据集上进行数据挖掘
  4. 平均值修正:可用前后两个观测值的平均值修正该异常值

了解预测值的分布

Train_data['price']
Train_data['price'].value_counts()

大概了解训练集预测值的取值情况
使用无界约翰逊分布等查看预测值的总体分布情况

import scipy.stats as st
y = Train_data['price']
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)

价格不服从正态分布,所以在进行回归之前,它必须进行转换。虽然对数变换做得很好,但最佳拟合是无界约翰逊分布

  • 了解预测值的偏移值和峰值的情况,也可以使用skew(),kurt()方法查看所有特征的偏移值和峰值
sns.distplot(Train_data['price']);
print("Skewness: %f" % Train_data['price'].skew())
print("Kurtosis: %f" % Train_data['price'].kurt())
  • 查看预测值的频数
    使用hist这个直方图函数画出预测值的频数
plt.hist(Train_data['price'], orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()

如果价格大于某一个值以后的频数很少了,就可以这些数看成异常值,直接用填充或者删除,次数可以看到大于20000的值就极少了

特征

  • 类别特征和数字特征的获取
    可以用.colunms获取(前面已经删掉seller和offerType)所有的特证名
    将price值分离出来,即分离label预测值,再人为根据实际含义来区分类别特征和数字特征,对于没有直接label coding的数据可以直接用以下代码来获取
#数字特征
#numeric_features = Train_data.select_dtypes(include=[np.number])
#numeric_features.columns
#类型特征
#categorical_features = Train_data.select_dtypes(include=[np.object])
#categorical_features.columns

此处根据实际含义人为指定为

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' ]
categorical_features = ['name', 'model', 'brand', 'bodyType', 'fuelType', 'gearbox', 'notRepairedDamage', 'regionCode',]
  • 类型特征的nunique分布
    使用nunique()函数查看每个特征有多少个不一样的取值
#特征nunique分布
for cat_fea in categorical_features:
    print(cat_fea + "的特征分布如下:")
    print("{}特征有个{}不同的值".format(cat_fea, Train_data[cat_fea].nunique()))
    print(Train_data[cat_fea].value_counts())
  • 数字特征的分析
    相关性分析
    将price用append()添加到数字特征的后面,使用corr()函数分析数字特征两两之间的关系并打印所有数字特征和price之间的相关性
price_numeric = Train_data[numeric_features]
correlation = price_numeric.corr()
print(correlation['price'].sort_values(ascending = False),'\n')

可以使用热力图来可视化这些特征之间的相关性

f , ax = plt.subplots(figsize = (7, 7))

plt.title('Correlation of Numeric Features with Price',y=1,size=16)

sns.heatmap(correlation,square = True,  vmax=0.8)

可视化每个数字特征的分布情况

f = pd.melt(Train_data, value_vars=numeric_features)
g = sns.FacetGrid(f, col="variable",  col_wrap=2, sharex=False, sharey=False)
g = g.map(sns.distplot, "value")

pandas.melt(frame, id_vars=None, value_vars=None, var_name=None, value_name=‘value’, col_level=None)
frame:要处理的数据集。
id_vars:不需要被转换的列名。
value_vars:需要转换的列名,如果剩下的列全部都要转换,就不用写了。
var_name和value_name是自定义设置对应的列名。
col_level :如果列是MultiIndex,则使用此级别。

melt以后的结果是两列数据。一列是变量名variable,一列是值value,FacetGrid首先画一个图形的轮廓出来,map函数将值填入其中,可视化以后可以看出匿名特征的分布相对均匀
还可以使用pairplot将数字特征之间的关系可视化

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()

多变量间的关系可视化可参考此处

  • 类别特征分析
    同数字特征分析步骤一样,观察unique分布,将分布特征进行可视化
    此处介绍一下类别特征的箱型图可视化,因为name和regionCode的类别太稀疏了,这里就把不稀疏的几类画一下
categorical_features = ['model',
 'brand',
 'bodyType',
 'fuelType',
 'gearbox',
 'notRepairedDamage']
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=plt.xticks(rotation=90)

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)

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")

用pandas_profiling生成数据报告

用pandas_profiling生成一个较为全面的可视化和数据报告(较为简单、方便) 最终打开html文件即可

import pandas_profiling

pfr = pandas_profiling.ProfileReport(Train_data)
pfr.to_file("./example.html")

总结

是指对已有的数据(特别是调查或观察得来的原始数据)在尽量少的先验假定下进行探索,通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律的一种数据分析方法。
数据探索有利于我们发现数据的一些特性,数据之间的关联性,对于后续的特征构建是很有帮助的。

  1. 对于数据的初步分析(直接查看数据,或.sum(), .mean(),.descirbe()等统计函数)可以从:样本数量,训练集数量,是否有时间特征,是否是时许问题,特征所表示的含义(非匿名特征),特征类型(字符类似,int,float,time),特征的缺失情况(注意缺失的在数据中的表现形式,有些是空的有些是”NAN”符号等),特征的均值方差情况。

  2. 分析记录某些特征值缺失占比30%以上样本的缺失处理,有助于后续的模型验证和调节,分析特征应该是填充(填充方式是什么,均值填充,0填充,众数填充等),还是舍去,还是先做样本分类用不同的特征模型去预测。

  3. 对于异常值做专门的分析,分析特征异常的label是否为异常值(或者偏离均值较远或者事特殊符号),异常值是否应该剔除,还是用正常值填充,是记录异常,还是机器本身异常等。

  4. 对于Label做专门的分析,分析标签的分布情况等。

  5. 进步分析可以通过对特征作图,特征和label联合做图(统计图,离散图),直观了解特征的分布情况,通过这一步也可以发现数据之中的一些异常值等,通过箱型图分析一些特征值的偏离情况,对于特征和特征联合作图,对于特征和label联合作图,分析其中的一些关联性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值