机器学习python小小白

二手车价格预测1:数据集探索

2020-03-23  本文已影响0人  凡有言说

该系列是用于记录跟随Datawhale入门数据挖掘的笔记,感谢Datawhale与天池联合发起的赛事——二手车交易价格预测。

链接:零基础入门数据挖掘 - 二手车交易价格预测

一、赛题背景

赛题以预测二手车的交易价格为任务,数据集报名后可见并可下载,该数据来自某交易平台的二手车交易记录,总数据量超过40w,包含31列变量信息,其中15列为匿名变量。为了保证比赛的公平性,将会从中抽取15万条作为训练集,5万条作为测试集A,5万条作为测试集B,同时会对name、model、brand和regionCode等信息进行脱敏。

image.png

二、数据集探索

1.什么是数据集探索(EDA)?

Exploratory Data Analysis refers to the critical process of performing initial investigations on data so as to discover patterns,to spot anomalies,to test hypothesis and to check assumptions with the help of summary statistics and graphical representations(Prasad Patil).

相关资料:
wikipedia:Exploratory data analysis
cmu:Exploratory Data Analysis
What is Exploratory Data Analysis?

2.载入函数

# 数据科学库
import pandas as pd
import numpy as np
from scipy.special import jn

#数据可视化库
import matplotlib.pyplot as plt
import seaborn as sns
import missingno as msno #缺失值可视化

#忽略警告语句
import warnings
warnings.filterwarnings('ignore')

3.载入数据

train_data = pd.read_csv('C:/Users/Van/Desktop/Datawhale数据挖掘/used_car_train_20200313.csv',  engine='python', sep = ' ')
test_data = pd.read_csv('C:/Users/Van/Desktop/Datawhale数据挖掘/used_car_testA_20200313.csv',  engine='python', sep = ' ')

4.简略观察数据

4.1 首末数据

#训练集
train_data.head().append(train_data.tail())

#测试集
test_data.head().append(test_data.tail())

4.2 数据形状

#训练集
train_data.shape

#测试集
test_data.shape

如果对自己的pandas等操作不放心,建议执行一步看一下head, tail, shape,这样有助于理解函数并进行操作。同时,也能避免连串的错误。

5.数据总览

5.1基本统计量

describe函数会输出每列的统计量:count、mean、std、min、25%、 50%、 75% 和最大值,这些信息可以帮助我们快速分析出数据的大概范围以及异常值。这里需要注意有时我们会看到999 9999 -1 等值,这些其实都是nan的另外一种表达方式。

#训练集
train_data.describe()

#测试集
test_data.describe()

5.2数据类型

info函数能够帮助我们了解每列数据的type,有助于了解是否存在除了nan以外的异常。

#训练集
train_data.info()

#测试集
test_data.info()

6.数据检测

6.1缺失值检测

6.1.1查看每列缺失值情况

# 训练集
train_data.isnull().sum()

# 测试集
test_data.isnull().sum()

6.1.2缺失值可视化

通过以上代码,我们可以很直观的了解哪些列存在缺失值。如果缺失值较少,我们可以选择填充,但如果缺失值过多,则需要考虑删除。

#训练集
missing = train_data.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace = True)
missing.plot.bar()
image.png
#测试集
missing = test_data.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace = True)
missing.plot.bar()
image.png

以下加载missingno包,它能够很直观地显示出数据缺失情况。

#训练集
#取了250个样本作为观察值
msno.matrix(train_data.sample(250))
image.png
#训练集
#取了1000个样本作为观察值
msno.bar(train_data.sample(1000))
image.png
#测试集
#取了250个样本作为观察值
msno.matrix(test_data.sample(250))
image.png
#测试集
#取了1000个样本作为观察值
msno.bar(test_data.sample(1000))
image.png

6.2异常值检测

6.2.1数据类型

#训练集
train_data.info()

由变量的类型可知,除了notRepairedDamage 为object类型其他都为数值型

#查看notRepairedDamage信息
train_data['notRepairedDamage'].value_counts()

#将notRepairedDamage中“-”替换成nan
train_data['notRepairedDamage'].replace('-', np.nan, inplace = True)

#查看notRepairedDamage信息
train_data['notRepairedDamage'].value_counts()

#查看缺失值情况
test_data.isnull().sum()

#测试集
test_data.info()

#查看notRepairedDamage信息
test_data['notRepairedDamage'].value_counts()

#将notRepairedDamage中“-”替换成nan
test_data['notRepairedDamage'].replace('-', np.nan, inplace = True)

#查看notRepairedDamage信息
test_data['notRepairedDamage'].value_counts()

test_data.isnull().sum()

6.2.1数据分布

通过对其他变量的观察,可以发现seller、offerType严重倾斜

#训练集
train_data["seller"].value_counts()
train_data["offerType"].value_counts()

del train_data["seller"]
del train_data["offerType"]

#测试集
test_data["seller"].value_counts()
test_data["offerType"].value_counts()

del test_data["seller"]
del test_data["offerType"]

7.预测值分布

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)
image.png

从上图可以看出,价格不服从正态分布,在进行回归前需要转换,其中无界约翰逊分布是最佳拟合。

7.2偏度和峰度

偏度(skewness)是用来衡量数据的不对称程度,峰度(Kurtosis)是用来衡量数据分布的尖锐程度。

sns.distplot(train_data['price']);
print("Skewness: %f" % train_data['price'].skew())
print("Kurtosis: %f" % train_data['price'].kurt())
image.png
train_data.skew(), train_data.kurt()

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

上图显示了训练集各属性的偏度与峰度的分布,可以看到大部分属性基本都符合正态分布,结合train_data.skew(), train_data.kurt()显示的具体数值可知,createdata和power不满足。

7.3预测值分布

plt.hist(Train_data['price'], orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()
image.png

可以看出大于20000得值极少

#log变换
plt.hist(np.log(train_data['price']), orientation = 'vertical',histtype = 'bar', color ='red') 
plt.show()
image.png

这里有一个技巧:对price取对数后,这样会使得分布更加均匀。

8.特征分析

8.1前期准备

#分离预测值
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',]

8.2类别特征

8.2.1唯一值

#训练集
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())

8.2.2箱型图

# 因为 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")
image.png

8.2.3小提琴图

catg_list = categorical_features
target = 'price'
for catg in catg_list :
    sns.violinplot(x=catg, y=target, data=train_data)
    plt.show()
image.png

8.2.4柱形图

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")
image.png

8.2.5条形图

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")
image.png

8.3数字特征

8.3.1前期准备

price_numeric = train_data[numeric_features]
correlation = price_numeric.corr()
print(correlation['price'].sort_values(ascending = False),'\n')

8.3.2相关性分析

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)
image.png

8.3.3偏度和峰度

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())  
         )
image.png

8.3.4数字特征的分布

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")
image.png

8.3.5数字特征的相互关系

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()
image.png

8.3.6多变量相互回归关系

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)
image.png

9.生成报告

import pandas_profiling
pfr = pandas_profiling.ProfileReport(train_data)
pfr.to_file("C:/Users/Van/Desktop/Datawhale数据挖掘/example.html")
数据集探索.png

参考资料:
What is Exploratory Data Analysis?
wikipedia:Exploratory data analysis
cmu:Exploratory Data Analysis
数据的偏度和峰度
Seaborn-05-Pairplot多变量图

上一篇下一篇

猜你喜欢

热点阅读