Task2 EDA-数据探索性分析

数据读取

导入相应包

#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 #缺失值可视化处理

读取csv文件

path = 'D:/二手车价格预测数据集/'
train_data = pd.read_csv(path+'used_car_train_20200313.csv',sep=' ') #sep='xx'以xx为数据分隔符
test_data = pd.read_csv(path+'used_car_testA_20200313.csv',sep=' ') #所有数据都是放在一列上的,以空格为分割,所以需要sep

EDA

数据总览

首先简单观察数据,这里拼接了训练集的首尾各5项

#简略观察数据(head()+shape)
train_data.head().append(train_data.tail()) #一共是150000 x 31
test_data.head().append(test_data.tail()) #一共是50000 x 30

使用describe()和info()观察数据

describe()主要获得数值型属性的平均值、方差、最大值、最小值等统计信息

train_data.describe()
test_data.describe()

info()主要获取每各属性的数据类型以及是否有值得缺失

train_data.info()
test_data.info()

判断数据缺失和异常

查看每个属性下缺失的数量

#查看列的缺失数量
train_data.isnull().sum()
test_data.isnull().sum()
# nan可视化,nan数量很小一般选择填充,如果使用lgb等树模型可以直接空缺,让树自己去优化,但如果nan存在的过多、可以考虑删掉
missing = train_data.isnull().sum()
missing = missing[missing > 0] #选取missing中>0的,也就是有缺失的
missing.sort_values(inplace=True) #排序
missing.plot.bar(color=['r','g','b']) #指定颜色,如果直方图>颜色数,则循环颜色

# 可视化看下缺失值
msno.matrix(train_data.sample(250)) #随机采样250个样本
msno.bar(test_data.sample(1000)) #采用msno中不同的可视化方法

在info()中发现,除了notRepairedDamage 为object类型其他都为数字,可以具体看一下

train_data['notRepairedDamage'].value_counts() # -就是nan
#将-替换成nan
train_data['notRepairedDamage'].replace('-', np.nan, inplace=True) #将-替代为nan
train_data['notRepairedDamage'].value_counts() #再看此时notRepairedDamage包含的值

严重倾斜的数据,一般不会对预测有什么帮助,故这边先删掉,当然也可以继续挖掘,但是一般意义不大

train_data["seller"].value_counts()
train_data["offerType"].value_counts()#结果发现seller和offerType两个属性的值严重倾斜,因此先删掉,注意:训练集和测试集都要删掉
del train_data["seller"]
del train_data["offerType"]
del test_data["seller"]
del test_data["offerType"]

了解预测值分布

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) #kde控制是否显示核密度估计图,fit是黑线用于拟合的概率分布,结果发现price的走势和无界约翰逊相似

查看skewness and kurtosis 偏度与峰度

#价格不服从正态分布,所以在进行回归之前,它必须进行转换。虽然对数变换做得很好,但最佳拟合是无界约翰逊分布
sns.distplot(train_data['price'])
print("Skewness: %f" % train_data['price'].skew()) #统计数据分布偏斜方向和程度的度量,是统计数据分布非对称程度的数字特征,正态分布偏度为0
print("Kurtosis: %f" % train_data['price'].kurt())#正态分布峰度为0,>0 比正态分布的高峰更加陡峭——尖顶峰,<0 比正态分布的高峰来得平台——平顶峰
print(train_data.skew())
print(train_data.kurt())

绘制训练数据的偏度和峰度

sns.distplot(train_data.skew(),color='blue',axlabel ='Skewness')
sns.distplot(train_data.kurt(),color='orange',axlabel ='Kurtness')

绘制price出现的频数

plt.hist(train_data['price'], orientation = 'vertical',histtype = 'bar', color ='red')#histype线条类型长方形
plt.show()
#大于20000得值极少,其实这里也可以把这些当作特殊得值(异常值)直接用填充或者删掉,再前面进行log变换之后的分布较均匀,可以进行log变换进行预测,这也是预测问题常用的trick
plt.hist(np.log(train_data['price']), orientation = 'vertical',histtype = 'bar', color ='red') 
plt.show() #log变换后更符合正态分布了
#分离y_train
Y_train = train_data['price']

数值属性和类别属性的分析

手工区分数值数型和类别属性

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分布

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())
for cat_fea in categorical_features:
    print(cat_fea + "的特征分布如下:")
    print("{}特征有个{}不同的值".format(cat_fea, test_data[cat_fea].nunique()))
    print(test_data[cat_fea].value_counts())

数值属性分析

numeric_features.append('price')
numeric_features

找出和price相关的属性

#相关性分析
price_numeric = train_data[numeric_features]
correlation = price_numeric.corr() #获得一个n x n的相关性矩阵,这里只需要数值属性
print(correlation['price'].sort_values(ascending = False),'\n') #只输出与price相关的
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) #绘制热力图,找到与price相关的属性
del price_numeric['price'] #随后删除数值属性中的price
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()))

每个数值特征的分布可视化

'''
pandas.melt()将列名转换为列数据(columns name → column values),重构DataFrame
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,则使用此级别。
pd.melt用于数据集的子集中分别可视化变量的分布或多个变量之间的关系时
FacetGrid使用数据集和用于构造网格的变量初始化对象。然后,可以通过调用FacetGrid.map()或将一个或多个绘图函数应用于每个子集
FacetGrid.map_dataframe()。最后,可以使用其他方法调整绘图,以执行更改轴标签,使用不同刻度或添加图例等操作
'''
f = pd.melt(train_data, value_vars=numeric_features) #保留数值型数据
g = sns.FacetGrid(f, col="variable",  col_wrap=2, sharex=False, sharey=False) #不共享x,y轴,col_wrap=2,表示最多两列,行数不限制
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') #sns.pairplot()绘制两两属性之间的关系,将 kind 参数设置为 "reg" 会为非对角线上的散点图拟合出一条回归直线,更直观地显示变量之间的关系
plt.show()
#多变量互相回归关系可视化,这里选取是之前相关性分析与price正相关的属性
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)
#regplot(x, y, data)绘制回归图。data参数是DataFram类型,x是其中某一列列名,是即将绘制的图的x坐标,y是其中某一列,是图的y坐标

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)

类别特征分析

for fea in categorical_features:
    print(train_data[fea].nunique())
categorical_features

类别特征箱形图可视化

# 因为 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') #填充缺失为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")#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")

用pandas_profiling生成数据报告

这个过程十分费时

import pandas_profiling

pfr = pandas_profiling.ProfileReport(train_data)
pfr.to_file("D:/二手车价格预测数据集/example.html")

参考:
[1]:https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.3.1cd8593a8bkYih&postId=95457

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值